diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000000000000000000000000000000000000..c2aedce950ac12ddb11163c806a6d2a7d9b1fdac
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.factorypath b/.factorypath
new file mode 100644
index 0000000000000000000000000000000000000000..28a1dbf2f05f70724b16347eddaf6c3f923a3fa2
--- /dev/null
+++ b/.factorypath
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/.project b/.project
new file mode 100644
index 0000000000000000000000000000000000000000..6e5affb8428dc2234f58b3c134cf0a7247de44fb
--- /dev/null
+++ b/.project
@@ -0,0 +1,28 @@
+
+
+ dap-patternsearch-analysis-service-standalone
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.springframework.ide.eclipse.boot.validation.springbootbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..29abf999564110a0d6aca109f55f439c72b7031c
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,6 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/=UTF-8
diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..dfa4f3adb289a4f7d73e0694f9045f99325604d7
--- /dev/null
+++ b/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations
+org.eclipse.jdt.apt.genTestSrcDir=target/generated-test-sources/test-annotations
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..90f7a5b4252676e8f4a2fc496e91f323aa99c1f5
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..f897a7f1cb2389f85fe6381425d29f0a9866fb65
--- /dev/null
+++ b/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/.settings/org.springframework.ide.eclipse.prefs b/.settings/org.springframework.ide.eclipse.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..a12794d68f2d05b47d56cfe2497dbde7752dc695
--- /dev/null
+++ b/.settings/org.springframework.ide.eclipse.prefs
@@ -0,0 +1,2 @@
+boot.validation.initialized=true
+eclipse.preferences.version=1
diff --git a/SEAL-3.5.1.tar.gz b/SEAL-3.5.1.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..34b1cca8970b7055a58a01594b2d130bebf3dde2
Binary files /dev/null and b/SEAL-3.5.1.tar.gz differ
diff --git a/bigpiseal3.5.1/.clang-format b/bigpiseal3.5.1/.clang-format
new file mode 100644
index 0000000000000000000000000000000000000000..59c40e85a9025b2c4a9b760aa2c2cf4e6e930cdb
--- /dev/null
+++ b/bigpiseal3.5.1/.clang-format
@@ -0,0 +1,127 @@
+---
+Language: Cpp
+# BasedOnStyle: Microsoft
+AccessModifierOffset: -4
+AlignAfterOpenBracket: AlwaysBreak
+AlignConsecutiveMacros: false
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Left
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllArgumentsOnNextLine: true
+AllowAllConstructorInitializersOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortLambdasOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterCaseLabel: true
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ AfterExternBlock: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom # Allman
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeBlocks: Merge
+IncludeCategories:
+ - Regex: '<.*>'
+ Priority: 1
+ - Regex: '"seal/util/.*"'
+ Priority: -2
+ - Regex: '"seal/.*"'
+ Priority: -3
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+IndentPPDirectives: None
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: All
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 1000
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Auto
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 4
+UseTab: Never
+...
+
diff --git a/bigpiseal3.5.1/.gitignore b/bigpiseal3.5.1/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..36d9e779c430f758b077095c99ad6d24a0baf610
--- /dev/null
+++ b/bigpiseal3.5.1/.gitignore
@@ -0,0 +1,342 @@
+# 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/
diff --git a/bigpiseal3.5.1/CHANGES.md b/bigpiseal3.5.1/CHANGES.md
new file mode 100644
index 0000000000000000000000000000000000000000..25358043ee9ef045e6508bfa1671c33008e28445
--- /dev/null
+++ b/bigpiseal3.5.1/CHANGES.md
@@ -0,0 +1,384 @@
+# List of Changes
+
+## Version 3.5.1
+
+Changed version to 3.5.1. The two hotfixes below are included.
+
+## Version 3.5.0
+
+### Hotfix - 4/30/2020
+
+- Fixed a critical bug [(Issue 166)](https://github.com/microsoft/SEAL/issues/166) in `Evaluator::multiply_plain_inplace`. Thanks s0l0ist!
+
+### Hotfix - 4/29/2020
+
+- Switched to using Microsoft GSL v3.0.1 and fixed minor GSL related issues in `CMakeLists.txt`.
+- Fixed some typos in [README.md](README.md).
+- Fixes bugs in ADO pipelines files.
+
+### New Features
+
+- Microsoft SEAL officially supports Android (Xamarin.Android) on ARM64.
+- Microsoft SEAL is a CMake project (UNIX-like systems only):
+ - There is now a top-level `CMakeLists.txt` that builds all native components.
+ - The following CMake targets are created: `SEAL::seal` (static library), `SEAL::seal_shared` (shared library; optional), `SEAL::sealc` (C export library; optional).
+ - Examples and unit tests are built if enabled through CMake (see [README.md](README.md)).
+ - ZLIB is downloaded and compiled by CMake and automatically included in the library.
+ - Microsoft GSL is downloaded by CMake. Its header files are copied to `native/src/gsl` and installed with Microsoft SEAL.
+ - Google Test is downloaded and compiled by CMake.
+- Improved serialization:
+ - `Serialization::SEALHeader` layout has been changed. SEAL 3.4 objects can still be loaded by SEAL 3.5, and the headers are automatically converted to SEAL 3.5 format.
+ - `Serialization::SEALHeader` captures version number information.
+ - Added examples for serialization.
+ - The seeded versions of `Encryptor`'s symmetric-key encryption and `KeyGenerator`'s `RelinKeys` and `GaloisKeys` generation now output `Serializable` objects. See more details in *API Changes* below.
+
+#### For Library Developers and Contributors
+
+We have created a set of C++ iterators that easily allows looping over polynomials in a ciphertext, over RNS components in a polynomial, and over coefficients in an RNS component.
+There are also a few other iterators that can come in handy.
+Currently `Evaluator` fully utilizes these, and in the future the rest of the library will as well.
+The iterators are primarily intended to be used with `std::for_each_n` to simplify existing code and help with code correctness.
+Please see [native/src/seal/util/iterator.h](native/src/seal/util/iterator.h) for guidance on how to use these.
+
+We have also completely rewritten the RNS tools that were previously in the `util::BaseConverter` class.
+This functionality is now split between two classes: `util::BaseConverter` whose sole purpose is to perform the `FastBConv` computation of [[BEHZ16]](https://eprint.iacr.org/2016/510) and `util::RNSTool` that handles almost everything else.
+RNS bases are now represented by the new `util::RNSBase` class.
+
+### API Changes
+
+The following changes are explained in C++ syntax and are introduced to .NET wrappers similarly:
+
+- New generic class `Serializable` wraps `Ciphertext`, `RelinKeys`, and `GaloisKeys` objects to provide a more flexible approach to the functionality provided in release 3.4 by `KeyGenerator::[relin|galois]_keys_save` and `Encryptor::encrypt_[zero_]symmetric_save` functions.
+Specifically, these functions have been removed and replaced with overloads of `KeyGenerator::[relin|galois]_keys` and `Encryptor::encrypt_[zero_]symmetric` that return `Serializable` objects.
+The `KeyGenerator::[relin|galois]_keys` methods in release 3.4 are renamed to `KeyGenerator::[relin|galois]_keys_local`.
+The `Serializable` objects cannot be used directly by the API, and are only intended to be serialized, which activates the compression functionalities introduced earlier in release 3.4.
+- `SmallModulus` class is renamed to `Modulus`, and is relocated to [native/src/seal/modulus.h](native/src/seal/modulus.h).
+- `*coeff_mod_count*` methods are renamed to `*coeff_modulus_size*`, which applies to many classes.
+- `parameter_error_name` and `parameter_error_message` methods are added to `EncryptionParameterQualifiers` and `SEALContext` classes to explain why an `EncryptionParameters` object is invalid.
+- The data members and layout of `Serialization::SEALHeader` have changed.
+
+The following changes are specific to C++:
+
+- New bounds in [native/src/seal/util/defines.h](native/src/seal/util/defines.h):
+ - `SEAL_POLY_MOD_DEGREE_MAX` is increased to 131072; values bigger than 32768 require the security check to be disabled by passing `sec_level_type::none` to `SEALContext::Create`.
+ - `SEAL_COEFF_MOD_COUNT_MAX` is increased to 64.
+ - `SEAL_MOD_BIT_COUNT_MAX` and `SEAL_MOD_BIT_COUNT_MIN` are added and set to 61 and 2, respectively.
+ - `SEAL_INTERNAL_MOD_BIT_COUNT` is added and set to 61.
+- `EncryptionParameterQualifiers` now has an error code `parameter_error` that interprets the reason why an `EncryptionParameter` object is invalid.
+- `bool parameters_set()` is added to replace the previous `bool parameters_set` member.
+
+The following changes are specific to .NET:
+
+- Version numbers are retrievable in .NET through `SEALVersion` class.
+
+### Other Changes
+
+- Releases are now listed on [releases page](https://github.com/microsoft/SEAL/releases).
+- The native library can serialize (save and load) objects larger than 4 GB.
+Please be aware that compressed serialization requires an additional temporary buffer roughly the size of the object to be allocated, and the streambuffer for the output stream may consume some non-trivial amount of memory as well.
+In the .NET library, objects are limited to 2 GB, and loading an object larger than 2 GB will throw an exception.
+[(Issue 142)](https://github.com/microsoft/SEAL/issues/142)
+- Larger-than-suggested parameters are supported for expert users.
+To enable that, please adjust `SEAL_POLY_MOD_DEGREE_MAX` and `SEAL_COEFF_MOD_COUNT_MAX` in [native/src/seal/util/defines.h](native/src/seal/util/defines.h).
+([Issue 150](https://github.com/microsoft/SEAL/issues/150),
+[Issue 84](https://github.com/microsoft/SEAL/issues/84))
+- Serialization now clearly indicates an insufficient buffer size error.
+[(Issue 117)](https://github.com/microsoft/SEAL/issues/117)
+- Unsupported compression mode now throws `std::invalid_argument` (native) or `ArgumentException` (.NET).
+- There is now a `.clang-format` for automated formatting of C++ (`.cpp` and `.h`) files.
+Execute `tools/scripts/clang-format-all.sh` for easy formatting (UNIX-like systems only).
+This is compatible with clang-format-9 and above.
+Formatting for C# is not yet supported.
+[(Issue 93)](https://github.com/microsoft/SEAL/issues/93)
+- The C export library previously in `dotnet/native/` is moved to [native/src/seal/c/](native/src/seal/c/) and renamed to SEAL_C to support building of wrapper libraries in languages like .NET, Java, Python, etc.
+- The .NET wrapper library targets .NET Standard 2.0, but the .NET example and test projects use C# 8.0 and require .NET Core 3.x. Therefore, Visual Studio 2017 is no longer supported for building the .NET example and test projects.
+- Fixed issue when compiling in FreeBSD.
+([PR 113](https://github.com/microsoft/SEAL/pull/113))
+- A [bug](https://eprint.iacr.org/2019/1266) in the [[BEHZ16]](https://eprint.iacr.org/2016/510)-style RNS operations is fixed; proper unit tests are added.
+- Performance of methods in `Evaluator` are in general improved.
+([PR 148](https://github.com/microsoft/SEAL/pull/148))
+This is compiler-dependent, however, and currently Clang seems to produce the fastest running code for Microsoft SEAL.
+
+### File Changes
+
+Renamed files and directories:
+
+- [dotnet/examples/7_Performance.cs](dotnet/examples/7_Performance.cs) was previously `dotnet/examples/6_Performance.cs`
+- [native/examples/7_performance.cpp](native/examples/7_performance.cpp) was previously `native/examples/6_performance.cpp`
+- [native/src/seal/c/](native/src/seal/c/) was previously `dotnet/native/sealnet`.
+- [native/src/seal/util/ntt.h](native/src/seal/util/ntt.h) was previously `native/src/seal/util/smallntt.h`.
+- [native/src/seal/util/ntt.cpp](native/src/seal/util/ntt.cpp) was previously `native/src/seal/util/smallntt.cpp`.
+- [native/tests/seal/util/ntt.cpp](native/tests/seal/util/ntt.cpp) was previously `native/tests/seal/util/smallntt.cpp`.
+
+New files:
+
+- [android/](android/)
+- [dotnet/examples/6_Serialization.cs](dotnet/examples/6_Serialization.cs)
+- [dotnet/src/Serializable.cs](dotnet/src/Serializable.cs)
+- [dotnet/src/Version.cs](dotnet/src/Version.cs)
+- [dotnet/tests/SerializationTests.cs](dotnet/tests/SerializationTests.cs)
+- [native/examples/6_serialization.cpp](native/examples/6_serialization.cpp)
+- [native/src/seal/c/version.h](native/src/seal/c/version.h)
+- [native/src/seal/c/version.cpp](native/src/seal/c/version.cpp)
+- [native/src/seal/util/galois.h](native/src/seal/util/galois.h)
+- [native/src/seal/util/galois.cpp](native/src/seal/util/galois.cpp)
+- [native/src/seal/util/hash.cpp](native/src/seal/util/hash.cpp)
+- [native/src/seal/util/iterator.h](native/src/seal/util/iterator.h)
+- [native/src/seal/util/rns.h](native/src/seal/util/rns.h)
+- [native/src/seal/util/rns.cpp](native/src/seal/util/rns.cpp)
+- [native/src/seal/util/streambuf.h](native/src/seal/util/streambuf.h)
+- [native/src/seal/util/streambuf.cpp](native/src/seal/util/streambuf.cpp)
+- [native/src/seal/serializable.h](native/src/seal/serializable.h)
+- [native/tests/seal/util/iterator.cpp](native/tests/seal/util/iterator.cpp)
+- [native/tests/seal/util/galois.cpp](native/tests/seal/util/galois.cpp)
+- [native/tests/seal/util/rns.cpp](native/tests/seal/util/rns.cpp)
+
+Removed files:
+
+- `dotnet/src/SmallModulus.cs` is merged to [dotnet/src/ModulusTests.cs](dotnet/src/Modulus.cs).
+- `dotnet/tests/SmallModulusTests.cs` is merged to [dotnet/tests/ModulusTests.cs](dotnet/tests/ModulusTests.cs).
+- `native/src/seal/util/baseconverter.h`
+- `native/src/seal/util/baseconverter.cpp`
+- `native/src/seal/smallmodulus.h` is merged to [native/src/seal/modulus.h](native/src/seal/modulus.h).
+- `native/src/seal/smallmodulus.cpp` is merged to [native/src/seal/modulus.cpp](native/src/seal/modulus.cpp).
+- `native/src/seal/c/smallmodulus.h` is merged to [native/src/seal/c/modulus.h](native/src/seal/c/modulus.h).
+- `native/src/seal/c/smallmodulus.cpp` is merged to [native/src/seal/c/modulus.cpp](native/src/seal/c/modulus.cpp).
+- `native/tests/seal/smallmodulus.cpp` is merged to [native/tests/seal/modulus.cpp](native/tests/seal/modulus.cpp).
+- `native/tests/seal/util/baseconverter.cpp`
+
+## Version 3.4.5
+
+- Fixed a concurrency issue in SEALNet: the `unordered_map` storing `SEALContext` pointers was not locked appropriately on construction and destruction of new `SEALContext` objects.
+- Fixed a few typos in examples ([PR 71](https://github.com/microsoft/SEAL/pull/71)).
+- Added include guard to config.h.in.
+
+## Version 3.4.4
+
+- Fixed issues with `SEALNet.targets` file and `SEALNet.nuspec.in`.
+- Updated `README.md` with information about existing multi-platform [NuGet package](https://www.nuget.org/packages/Microsoft.Research.SEALNet).
+
+## Version 3.4.3
+
+- Fixed bug in .NET serialization code where an incorrect number of bytes was written when using ZLIB compression.
+- Fixed an issue with .NET functions `Encryptor.EncryptSymmetric...`, where asymmetric encryption was done instead of symmetric encryption.
+- Prevented `KeyGenerator::galois_keys` and `KeyGenerator::relin_keys` from being called when the encryption parameters do not support keyswitching.
+- Fixed a bug in `Decryptor::invariant_noise_budget` where the computed noise budget was `log(plain_modulus)` bits smaller than it was supposed to be.
+- Removed support for Microsoft GSL `gsl::multi_span`, as it was recently deprecated in GSL.
+
+## Version 3.4.2
+
+- Fixed bug reported in [Issue 66](https://github.com/microsoft/SEAL/issues/66) on GitHub.
+- CMake does version matching now (correctly) only on major and minor version, not patch version, so writing `find_package(SEAL 3.4)` works correctly and selects the newest version `3.4.x` it can find.
+
+## Version 3.4.1
+
+This patch fixes a few issues with ZLIB support on Windows.
+Specifically,
+
+- Fixed a mistake in `native/src/CMakeConfig.cmd` where the CMake library search path
+suffix was incorrect.
+- Switched to using a static version of ZLIB on Windows.
+- Corrected instructions in [README.md](README.md) for enabling ZLIB support on Windows.
+
+## Version 3.4.0
+
+### New Features
+
+- Microsoft SEAL can use [ZLIB](https://github.com/madler/zlib), a data compression library, to automatically compress data that is serialized. This applies to every serializable object in Microsoft SEAL.
+This feature must be enabled by the user. See more explanation of the compression mechanism in [README.md](README.md#zlib).
+Microsoft SEAL does not redistribute ZLIB.
+- AES-128 is replaced with the BLAKE2 family of hash functions in the pseudorandom number generator, as BLAKE2 provides better cross-platform support.
+Microsoft SEAL redistributes the [reference implementation of BLAKE2](https://github.com/BLAKE2/BLAKE2) with light modifications to silence some misleading warnings in Visual Studio.
+The reference implementation of BLAKE2 is licensed under [CC0 1.0 Universal](https://github.com/BLAKE2/BLAKE2/blob/master/COPYING); see license boilerplates in files [native/src/seal/util/blake*](native/src/seal/util/).
+- The serialization functionality has been completely rewritten to make it more safe and robust.
+Every serialized Microsoft SEAL object starts with a 16-byte `Serialization::SEALHeader` struct, and then includes the data for the object member variables.
+Every serializable object can now also be directly serialized into a memory buffer instead of a C++ stream.
+This improves serialization for .NET and makes it much easier to wrap the serialization functionality in other languages, e.g., Java.
+Unfortunately, old serialized Microsoft SEAL objects are incompatible with the new format.
+- A ciphertext encrypted with a secret key, for example, a keyswitching key, has one component generated by the PRNG.
+By using a seeded PRNG, this component can be replaced with the random seed used by the PRNG to reduce data size.
+After transmitted to another party with Microsoft SEAL, the component can be restored (regenerated) with the same seed.
+The security of using seeded PRNG is enhanced by switching to BLAKE2 hash function with a 512-bit seed.
+- `Encryptor` now can be constructed with a secret key.
+This enables symmetric key encryption which has methods that serialize ciphertexts (compressed with a seed) to a C++ stream or a memory buffer.
+- The CMake system has been improved.
+For example, multiple versions of Microsoft SEAL can now be installed on the same system easily, as the default installation directory and library filename now depend on the version of Microsoft SEAL.
+Examples and unit tests can now be built without installing the library.
+[README.md](README.md) has been updated to reflect these changes.
+- `Encryptor::encrypt` operations in the BFV scheme are modified.
+Each coefficient of a plaintext message is first multiplied with the ciphertext modulus, then divided by the plaintext modulus, and rounded to the nearest integer.
+In comparison with the previous method, where each coefficient of a plaintext message is multiplied with the flooring of the coefficient modulus divided by the plaintext modulus, the new method reduces the noise introduced in encryption, increases a noise budget of a fresh encryption, slightly slows down encryption, and has no impact on the security at all.
+- Merged [PR 62](https://github.com/microsoft/SEAL/pull/62) that uses a non-adjacent form (NAF) decomposition of random rotations to perform them in a minimal way from power-of-two rotations in both directions.
+- This improves performance of random rotations.
+
+### API Changes
+
+#### C++ Native
+
+In all classes with `save` and `load` methods:
+
+- Replaced the old `save` with two new methods that saves to either a C++ stream or a memory buffer.
+Optionally, a compression mode can be chosen when saving an object.
+- Replaced the old `load` with two new methods that loads from either a C++ stream or a memory buffer.
+- Added a method `save_size` to get an upper bound on the size of the object as if it was written to an output stream.
+To save to a buffer, the user must ensure that the buffer has at least size equal to what the `save_size` member function returns.
+- New `save` and `load` methods rely on the `Serialization` class declared in `serialization.h`.
+This class unifies the serialization functionality for all serializable Microsoft SEAL classes.
+
+In class `Ciphertext`:
+
+- Added a method `int_array` for read-only access to the underlying `IntArray` object.
+- Removed methods `uint64_count_capacity` and `uint64_count` that can now be accessed in a more descriptive manner through the `int_array` return value.
+
+In class `CKKSEncoder`: added support for `gsl::span` type of input.
+
+In class `SEALContext::ContextData`: added method `coeff_mod_plain_modulus` for read-only access to the non-RNS version of `upper_half_increment`.
+
+In class `EncryptionParameters`: an `EncryptionParameters` object can be constructed without `scheme_type` which by default is set to `scheme_type::none`.
+
+In class `Encryptor`:
+
+- An `Encryptor` object can now be constructed with a secret key to enable symmetric key encryption.
+- Added methods `encrypt_symmetric` and `encrypt_zero_symmetric` that generate a `Ciphertext` using the secret key.
+- Added methods `encrypt_symmetric_save` and `encrypt_zero_symmetric_save` that directly serialize the resulting `Ciphertext` to a C++ stream or a memory buffer.
+The resulting `Ciphertext` no long exists after serilization.
+In these methods, the second polynomial of a ciphertext is generated by the PRNG and is replaced with the random seed used.
+
+In class `KeyGenerator`:
+
+- Added methods `relin_keys_save` and `galois_keys_save` that generate and directly serialize keys to a C++ stream or a memory buffer.
+The resulting keys no long exist after serilization.
+In these methods, half of the polynomials in keys are generated by the PRNG and is replaced with the random seed used.
+- Methods `galois_keys` and `galois_keys_save` throw an exception if `EncryptionParameters` do not support batching in the BFV scheme.
+
+In class `Plaintext`: added a method `int_array` for read-only access to the underlying `IntArray` object.
+
+In class `UniformRandomGenerator` and `UniformRandomGeneratorFactory`: redesigned for users to implement their own random number generators more easily.
+
+In file `valcheck.h`: validity checks are partitioned into finer methods; the `is_valid_for(...)` functions will validate all aspects fo the Microsoft SEAL ojects.
+
+New classes `BlakePRNG` and `BlakePRNGFactory`: uses Blake2 family of hash functions for PRNG.
+
+New class `Serialization`:
+
+- Gives a uniform serialization in Microsoft SEAL to save objects to a C++ stream or a memory buffer.
+- Can be configured to use ZLIB compression.
+
+New files:
+
+- [native/src/seal/util/rlwe.h](native/src/seal/util/rlwe.h)
+- [native/src/seal/util/blake2.h](native/src/seal/util/blake2.h)
+- [native/src/seal/util/blake2-impl.h](native/src/seal/util/blake2-impl.h)
+- [native/src/seal/util/blake2b.c](native/src/seal/util/blake2b.c)
+- [native/src/seal/util/blake2xb.c](native/src/seal/util/blake2xb.c)
+- [native/src/seal/util/croots.cpp](native/src/seal/util/croots.cpp)
+- [native/src/seal/util/croots.h](native/src/seal/util/croots.h)
+- [native/src/seal/util/scalingvariant.cpp](native/src/seal/util/scalingvariant.cpp)
+- [native/src/seal/util/scalingvariant.h](native/src/seal/util/scalingvariant.h)
+- [native/src/seal/util/ztools.cpp](native/src/seal/util/ztools.cpp)
+- [native/src/seal/util/ztools.h](native/src/seal/util/ztools.h)
+- [native/src/seal/serialization.cpp](native/src/seal/serialization.cpp)
+- [native/src/seal/serialization.h](native/src/seal/serialization.h)
+- [native/tests/seal/serialization.cpp](native/tests/seal/serialization.cpp)
+- [dotnet/native/sealnet/serialization_wrapper.cpp](dotnet/native/sealnet/serialization_wrapper.cpp)
+- [dotnet/native/sealnet/serialization_wrapper.h](dotnet/native/sealnet/serialization_wrapper.h)
+
+Removed files:
+
+- [native/src/seal/util/hash.cpp](native/src/seal/util/hash.cpp)
+
+#### .NET
+
+API changes are mostly identical in terms of functionality to those in C++ native, except only the `IsValidFor` variant of the validity check functions is available in .NET, the more granular checks are not exposed.
+
+New files:
+
+- [dotnet/src/Serialization.cs](dotnet/src/Serialization.cs)
+
+### Minor Bug and Typo Fixes
+
+- Function `encrypt_zero_asymmetric` in [native/src/seal/util/rlwe.h](native/src/seal/util/rlwe.h) handles the condition `is_ntt_form == false` correctly.
+- Invariant noise calculation in BFV is now correct when the plaintext modulus is large and ciphertexts are fresh (reported in [issue 59](https://github.com/microsoft/SEAL/issues/59)).
+- Fixed comments in [native/src/seal/util/smallntt.cpp](native/src/seal/util/smallntt.cpp) as reported in [issue 56](https://github.com/microsoft/SEAL/issues/56).
+- Fixed an error in examples as reported in [issue 61](https://github.com/microsoft/SEAL/issues/61).
+- `GaloisKeys` can no longer be created with encryption parameters that do not support batching.
+- Security issues in deserialization were resolved.
+
+## Version 3.3.2 (patch)
+
+### Minor Bug and Typo Fixes
+
+- Switched to using RNS rounding instead of RNS flooring to fix the CKKS
+accuracy issue reported in [issue 52](https://github.com/microsoft/SEAL/issues/52).
+- Added support for QUIET option in CMake (`find_package(seal QUIET)`).
+- Using `[[nodiscard]]` attribute when compiling as C++17.
+- Fixed a bug in `Evaluator::multiply_many` where the input vector was changed.
+
+## Version 3.3.1 (patch)
+
+### Minor Bug and Typo Fixes
+
+- A bug was fixed that introduced significant extra inaccuracy in CKKS when compiled on Linux, at least with some versions of glibc; Windows and macOS were not affected.
+- A bug was fixed where, on 32-bit platforms, some versions of GCC resolved the util::reverse_bits function to the incorrect overload.
+
+## Version 3.3.0
+
+### New Features
+
+In this version, we have significantly improved the usability of the CKKS scheme in Microsoft SEAL and many of these improvements apply to the BFV scheme as well.
+Homomorphic operations that are based on key switching, i.e., relinearization and rotation, do not consume any noise budget (BFV) or impact accuracy (CKKS).
+The implementations of these operations are significantly simplified and unified, and no longer use bit decomposition, so decomposition bit count is gone.
+Moreover, fresh ciphertexts now have lower noise.
+These changes have an effect on the API and it will be especially worthwhile for users of older versions of the library to study the examples and comments in [native/examples/3_levels.cpp](native/examples/3_levels.cpp) (C++) or [dotnet/examples/3_Levels.cs](dotnet/examples/3_Levels.cs) (C#).
+
+The setup of `EncryptionParameters` has been made both easier and safer (see [API Changes](#api-changes) below).
+
+The examples in [native/examples/](native/examples/) and [dotnet/examples/](dotnet/examples/) have been redesigned to better teach the multiple technical concepts required to use Microsoft SEAL correctly and efficiently, and more compactly demonstrate the API.
+
+### API Changes
+
+Deleted header files:
+
+- `native/defaultparameters.h`
+
+New header files:
+
+- [native/src/seal/kswitchkeys.h](native/src/seal/kswitchkeys.h): new base class for `RelinKeys` and `GaloisKeys`)
+- [native/src/seal/modulus.h](native/src/seal/modulus.h): static helper functions for parameter selection
+- [native/src/seal/valcheck.h](native/src/seal/valcheck.h): object validity check functionality
+- [native/src/seal/util/rlwe.h](native/src/seal/util/rlwe.h)
+
+In class `SEALContext`:
+
+- Replaced `context_data(parms_id_type)` with `get_context_data(parms_id_type)`.
+- Removed `context_data()`.
+- Added `key_context_data()`, `key_parms_id()`, `first_context_data()`, and `last_context_data()`.
+- Added `using_keyswitching()` that indicates whether key switching is supported in this `SEALContext`.
+- `Create(...)` in C++, and constructor in C#, now accepts an optional security level based on [HomomorphicEncryption.org](https://HomomorphicEncryption.org) security standard, causing it to enforce the specified security level.
+By default a 128-bit security level is used.
+- Added `prev_context_data()` method to class `ContextData` (doubly linked modulus switching chain).
+- In C# `SEALContext` now has a public constructor.
+
+Parameter selection:
+
+- Removed the `DefaultParams` class.
+- Default `coeff_modulus` for the BFV scheme are now accessed through the function `CoeffModulus::BFVDefault(...)`.
+These moduli are not recommended for the CKKS scheme.
+- Customized `coeff_modulus` for the CKKS scheme can be created using `CoeffModulus::Create(...)` which takes the `poly_modulus_degree` and a vector of bit-lengths of the prime factors as arguments.
+It samples suitable primes close to 2^bit_length and returns a vector of `SmallModulus` elements.
+- `PlainModulus::Batching(...)` can be used to sample a prime for `plain_modulus` that supports `BatchEncoder` for the BFV scheme.
+
+Other important changes:
+
+- Removed `size_capacity` function and data members from `Ciphertext` class.
+- Moved all validation methods such as `is_valid_for` and `is_metadata_valid_for` to `valcheck.h`.
+- Removed argument `decomposition_bit_count` from methods `relin_keys(...)` and `galois_keys(...)` in class `KeyGenerator`.
+- It is no longer possible to create more than one relinearization key.
+This is to simplify the API and reduce confusion. We have never seen a real use-case where more relinearization keys would be a good idea.
+- Added methods to generate an encryption of zero to `Encryptor`.
+- Added comparison methods and primality check for `SmallModulus`.
+- Classes `RelinKeys` and `GaloisKeys` are now derived from a common base class `KSwitchKeys`.
+- GoogleTest framework is now included as a Git submodule.
+- Numerous bugs have been fixed, particularly in the .NET wrappers.
+
+## Version 3.2
diff --git a/bigpiseal3.5.1/CMakeLists.txt b/bigpiseal3.5.1/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5696d3cb76fe1b3a0640f4b59b2da95ee1a4bb0e
--- /dev/null
+++ b/bigpiseal3.5.1/CMakeLists.txt
@@ -0,0 +1,809 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT license.
+
+cmake_minimum_required(VERSION 3.12)
+
+###################################################
+# Project SEAL includes the following components: #
+# 1. SEAL C++ library #
+# 2. SEAL C export library #
+# 3. SEAL C++ examples #
+# 4. SEAL C++ tests #
+###################################################
+
+project(SEAL VERSION 3.5.1 LANGUAGES CXX C)
+
+# Check operating system: for Windows, use Visual Studio solution/project files.
+if(MSVC)
+ if(ALLOW_COMMAND_LINE_BUILD)
+ message(STATUS "Configuring for Visual Studio")
+ else()
+ message(FATAL_ERROR "Please build Microsoft SEAL using the attached Visual Studio solution/project files")
+ endif()
+endif()
+
+########################
+# Global configuration #
+########################
+
+# [Option] CMAKE_BUILD_TYPE
+# Build in Release mode by default; otherwise use selected option
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
+ STRINGS "Release" "Debug" "MinSizeRel" "RelWithDebInfo")
+endif()
+message(STATUS "Build type (CMAKE_BUILD_TYPE): ${CMAKE_BUILD_TYPE}")
+
+# [Flag] SEAL_DEBUG
+# In Debug mode, enable SEAL_DEBUG
+if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ set(SEAL_DEBUG ON)
+else()
+ set(SEAL_DEBUG OFF)
+endif()
+message(STATUS "Microsoft SEAL debug mode: ${SEAL_DEBUG}")
+
+# [Option] SEAL_USE_CXX17
+# Should we use C++14 or C++17?
+set(SEAL_USE_CXX17_OPTION_STR "Use C++17")
+option(SEAL_USE_CXX17 ${SEAL_USE_CXX17_OPTION_STR} ON)
+
+# Conditionally enable features from C++17
+set(SEAL_USE_STD_BYTE OFF)
+set(SEAL_USE_SHARED_MUTEX OFF)
+set(SEAL_USE_IF_CONSTEXPR OFF)
+set(SEAL_USE_MAYBE_UNUSED OFF)
+set(SEAL_USE_NODISCARD OFF)
+set(SEAL_USE_STD_FOR_EACH_N OFF)
+set(SEAL_LANG_FLAG "-std=c++14")
+if(SEAL_USE_CXX17)
+ set(SEAL_USE_STD_BYTE ON)
+ set(SEAL_USE_SHARED_MUTEX ON)
+ set(SEAL_USE_IF_CONSTEXPR ON)
+ set(SEAL_USE_MAYBE_UNUSED ON)
+ set(SEAL_USE_NODISCARD ON)
+ set(SEAL_USE_STD_FOR_EACH_N ON)
+ set(SEAL_LANG_FLAG "-std=c++17")
+endif()
+
+# [Option] CXX compiler flags
+# For easier adding of CXX compiler flags
+include(CheckCXXCompilerFlag)
+function(enable_cxx_compiler_flag_if_supported flag)
+ string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_already_set)
+ if(flag_already_set EQUAL -1)
+ message(STATUS "Adding CXX compiler flag: ${flag} ...")
+ check_cxx_compiler_flag("${flag}" flag_supported)
+ if(flag_supported)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
+ endif()
+ unset(flag_supported CACHE)
+ endif()
+endfunction()
+
+# Always build position-independent-code
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+# Don't make the install target depend on the all target.
+set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY ON)
+
+# In Debug mode, enable extra compiler flags.
+if(NOT MSVC AND SEAL_DEBUG)
+ enable_cxx_compiler_flag_if_supported("-Wall")
+ enable_cxx_compiler_flag_if_supported("-Wextra")
+ enable_cxx_compiler_flag_if_supported("-Wconversion")
+ enable_cxx_compiler_flag_if_supported("-Wshadow")
+ enable_cxx_compiler_flag_if_supported("-pedantic")
+endif()
+
+# Path for outupt
+if(ANDROID_ABI)
+ # Android compiles several targets at the same time. Need to specify
+ # separate directories for separate ABIs.
+ set(OUTLIB_PATH "lib/${ANDROID_ABI}")
+else()
+ set(OUTLIB_PATH "lib")
+endif()
+
+# Required files and directories
+include(GNUInstallDirs)
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${SEAL_SOURCE_DIR}/${OUTLIB_PATH})
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${SEAL_SOURCE_DIR}/${OUTLIB_PATH})
+set(CMAKE_LIBRARY_RUNTIME_DIRECTORY ${SEAL_SOURCE_DIR}/bin)
+set(SEAL_TARGETS_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALTargets.cmake)
+set(SEAL_CONFIG_IN_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALConfig.cmake.in)
+set(SEAL_CONFIG_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALConfig.cmake)
+set(SEAL_CONFIG_VERSION_FILENAME ${SEAL_SOURCE_DIR}/cmake/SEALConfigVersion.cmake)
+set(SEAL_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/SEAL-${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR})
+set(SEAL_INCLUDES_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/SEAL-${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR})
+set(SEAL_INCLUDES_BUILD_DIR ${SEAL_SOURCE_DIR}/native/src)
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${SEAL_SOURCE_DIR}/bin)
+
+# For extra modules we might have
+list(APPEND CMAKE_MODULE_PATH ${SEAL_SOURCE_DIR}/cmake)
+
+include(CMakePushCheckState)
+include(CMakeDependentOption)
+include(CheckIncludeFiles)
+include(CheckCXXSourceCompiles)
+include(CheckCXXSourceRuns)
+include(CheckTypeSize)
+
+# We clean up native/src/gsl directory which is no longer used in version >= 3.5.0
+if(NOT MSVC AND EXISTS ${SEAL_INCLUDES_BUILD_DIR}/gsl)
+ message(STATUS "Removing ${SEAL_INCLUDES_BUILD_DIR}/gsl; this is no longer used by Microsoft SEAL >= 3.5.0")
+ file(REMOVE_RECURSE ${SEAL_INCLUDES_BUILD_DIR}/gsl)
+endif()
+
+##################################
+# Macros for configuring targets #
+##################################
+
+# Set the C++ language version
+macro(set_language target)
+ if(SEAL_USE_CXX17)
+ target_compile_features(${target} PUBLIC cxx_std_17)
+ else()
+ target_compile_features(${target} PUBLIC cxx_std_14)
+ endif()
+endmacro()
+
+# Set the VERSION property
+macro(set_version target)
+ set_target_properties(${target} PROPERTIES VERSION ${SEAL_VERSION})
+endmacro()
+
+# Set the library filename to reflect version
+macro(set_version_filename target)
+ set_target_properties(${target} PROPERTIES
+ OUTPUT_NAME ${target}-${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR})
+endmacro()
+
+# Set the SOVERSION property
+macro(set_soversion target)
+ set_target_properties(${target} PROPERTIES
+ SOVERSION ${SEAL_VERSION_MAJOR}.${SEAL_VERSION_MINOR})
+endmacro()
+
+# Set include directories for build and install interfaces
+macro(set_include_directories target)
+ target_include_directories(${target} PUBLIC
+ $
+ $)
+endmacro()
+
+# Link a thread library
+macro(link_threads target)
+ # Require thread library
+ if(NOT TARGET Threads::Threads)
+ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+ set(THREADS_PREFER_PTHREAD_FLAG TRUE)
+ find_package(Threads REQUIRED)
+ endif()
+
+ # Link Threads
+ target_link_libraries(${target} PUBLIC Threads::Threads)
+endmacro()
+
+# Include target to given export
+macro(install_target target export)
+ install(TARGETS ${target} EXPORT ${export}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+endmacro()
+
+#########################
+# External dependencies #
+#########################
+
+function(create_cache_entries dir_name)
+ set(cce_file_name ${dir_name}/cache_init.txt)
+ file(WRITE "${cce_file_name}" "set(CMAKE_C_COMPILER \"${CMAKE_C_COMPILER}\" CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(CMAKE_CXX_COMPILER \"${CMAKE_CXX_COMPILER}\" CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(CMAKE_TOOLCHAIN_FILE \"${CMAKE_TOOLCHAIN_FILE}\" CACHE FILEPATH \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(ANDROID_ABI ${ANDROID_ABI} CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(ANDROID_NDK \"${ANDROID_NDK}\" CACHE FILEPATH \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(ANDROID_PLATFORM ${ANDROID_PLATFORM} CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(CMAKE_ANDROID_ARCH_ABI ${CMAKE_ANDROID_ARCH_ABI} CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(CMAKE_ANDROID_NDK \"${CMAKE_ANDROID_NDK}\" CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\" CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME} CACHE STRING \"\" FORCE)\n")
+ file(APPEND "${cce_file_name}" "set(CMAKE_SYSTEM_VERSION ${CMAKE_SYSTEM_VERSION} CACHE STRING \"\" FORCE)\n")
+endfunction()
+
+set(THIRDPARTY_DIR ${SEAL_SOURCE_DIR}/thirdparty)
+
+# [option] SEAL_USE_MSGSL
+set(SEAL_USE_MSGSL_OPTION_STR "Use Microsoft GSL")
+option(SEAL_USE_MSGSL ${SEAL_USE_MSGSL_OPTION_STR} ON)
+
+# Download and configure
+if(SEAL_USE_MSGSL AND NOT MSVC)
+ message(STATUS "Setting up MSGSL ...")
+ if(NOT CMAKE_TOOLCHAIN_FILE)
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/msgsl)
+ else()
+ create_cache_entries(${THIRDPARTY_DIR}/msgsl)
+ if(EXISTS ${THIRDPARTY_DIR}/msgsl/CMakeCache.txt)
+ # Force regenerating make files. When cross compiling we might be
+ # compiling more than one platform at a time.
+ file(REMOVE ${THIRDPARTY_DIR}/msgsl/CMakeCache.txt)
+ endif()
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -Ccache_init.txt
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/msgsl)
+ endif()
+ if(result)
+ message(WARNING "Failed to download MSGSL (${result}); disabling `SEAL_USE_MSGSL`")
+ endif()
+endif()
+
+# Build
+if(SEAL_USE_MSGSL AND NOT MSVC)
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} --build .
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/msgsl)
+ if(result)
+ message(WARNING "Failed to build MSGSL (${result}); disabling `SEAL_USE_MSGSL`")
+ endif()
+ set(GSL_CXX_STANDARD "14" CACHE STRING "" FORCE)
+ mark_as_advanced(GSL_CXX_STANDARD )
+ set(GSL_TEST OFF CACHE BOOL "" FORCE)
+ mark_as_advanced(GSL_TEST)
+endif()
+
+# Set up the targets
+if(SEAL_USE_MSGSL AND NOT MSVC)
+ add_subdirectory(
+ ${THIRDPARTY_DIR}/msgsl/src
+ EXCLUDE_FROM_ALL)
+ set(MSGSL_INCLUDE_DIR ${THIRDPARTY_DIR}/msgsl/src/include)
+endif()
+
+# [option] SEAL_USE_ZLIB
+set(SEAL_USE_ZLIB_OPTION_STR "Use ZLIB for compressed serialization")
+option(SEAL_USE_ZLIB ${SEAL_USE_ZLIB_OPTION_STR} ON)
+
+# ZLIB has no VERSION given to project(), needs to suppress CMP0048 warning
+if(SEAL_USE_ZLIB AND NOT MSVC)
+ set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS TRUE CACHE INTERNAL "Suppress CMP0048 warning" FORCE)
+endif()
+
+# Download and configure
+if(SEAL_USE_ZLIB AND NOT MSVC)
+ message(STATUS "Setting up ZLIB ...")
+
+ if(NOT CMAKE_TOOLCHAIN_FILE)
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/zlib)
+ else()
+ create_cache_entries(${THIRDPARTY_DIR}/zlib)
+ if(EXISTS ${THIRDPARTY_DIR}/zlib/CMakeCache.txt)
+ # Force regenerating make files. When cross compiling we might be
+ # compiling more than one platform at a time.
+ file(REMOVE ${THIRDPARTY_DIR}/zlib/CMakeCache.txt)
+ endif()
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -Ccache_init.txt
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/zlib)
+ endif()
+ if(result)
+ message(WARNING "Failed to download ZLIB (${result}); disabling `SEAL_USE_ZLIB`")
+ endif()
+ mark_as_advanced(AMD64)
+ mark_as_advanced(ASM686)
+ mark_as_advanced(EXECUTABLE_OUTPUT_PATH)
+ mark_as_advanced(CMAKE_INSTALL_PREFIX)
+ mark_as_advanced(INSTALL_BIN_DIR)
+ mark_as_advanced(INSTALL_INC_DIR)
+ mark_as_advanced(INSTALL_LIB_DIR)
+ mark_as_advanced(INSTALL_MAN_DIR)
+ mark_as_advanced(INSTALL_PKGCONFIG_DIR)
+ mark_as_advanced(LIBRARY_OUTPUT_PATH)
+ mark_as_advanced(CMAKE_BACKWARDS_COMPATIBILITY)
+endif()
+
+# Build
+if(SEAL_USE_ZLIB AND NOT MSVC)
+ execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/zlib)
+ if(result)
+ message(WARNING "Failed to build ZLIB (${result}); disabling `SEAL_USE_ZLIB`")
+ endif()
+endif()
+
+# Set up the targets
+if(SEAL_USE_ZLIB AND NOT MSVC)
+ add_subdirectory(
+ ${THIRDPARTY_DIR}/zlib/src
+ EXCLUDE_FROM_ALL)
+ list(APPEND SEAL_ZLIB_INCLUDE_DIRS ${THIRDPARTY_DIR}/zlib/src)
+ list(APPEND SEAL_ZLIB_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/zlib/src)
+ set_target_properties(zlibstatic PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${SEAL_ZLIB_INCLUDE_DIRS}")
+ set(zlibstatic_LIBRARY_PATH ${THIRDPARTY_DIR}/zlib/src/libz.a)
+endif()
+
+# Google Test
+# This follows the example in
+# https://github.com/google/googletest/blob/release-1.10.0/googletest/README.md.
+
+# Download and configure
+if(SEAL_BUILD_TESTS AND NOT MSVC)
+ message(STATUS "Setting up Google Test ...")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/googletest)
+ if(result)
+ message(WARNING "Failed to download Google Test (${result}); disabling `SEAL_BUILD_TESTS`")
+ endif()
+ set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
+ mark_as_advanced(BUILD_GMOCK)
+ set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
+ mark_as_advanced(INSTALL_GTEST)
+endif()
+
+# Build
+if(SEAL_BUILD_TESTS AND NOT MSVC)
+ execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ OUTPUT_QUIET
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${THIRDPARTY_DIR}/googletest)
+ if(result)
+ message(WARNING "Failed to build Google Test (${result}); disabling `SEAL_BUILD_TESTS`")
+ endif()
+endif()
+
+# Set up the targets
+if(SEAL_BUILD_TESTS AND NOT MSVC)
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+ add_subdirectory(
+ ${THIRDPARTY_DIR}/googletest/src
+ ${THIRDPARTY_DIR}/googletest/build
+ EXCLUDE_FROM_ALL)
+endif()
+
+####################
+# SEAL C++ library #
+####################
+
+# Should we build also the shared library?
+set(BUILD_SHARED_LIBS_STR "Build shared library")
+option(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_STR} OFF)
+if(MSVC AND BUILD_SHARED_LIBS)
+ message(WARNING "This build system only supports a static build; disabling `BUILD_SHARED_LIBS`")
+ set(BUILD_SHARED_LIBS OFF CACHE BOOL ${BUILD_SHARED_LIBS_STR} FORCE)
+endif()
+
+# Throw on multiply_plain by a zero plaintext
+set(SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT_STR "Throw an exception when a member of Evaluator outputs a transparent ciphertext")
+option(SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT ${SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT_STR} ON)
+mark_as_advanced(FORCE SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT)
+
+# In some non-MSVC compilers std::for_each_n is not available even when compiling as C++17
+if(SEAL_USE_STD_FOR_EACH_N)
+ cmake_push_check_state(RESET)
+ set(CMAKE_REQUIRED_QUIET TRUE)
+
+ if(NOT MSVC)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -O0 ${SEAL_LANG_FLAG}")
+ check_cxx_source_compiles("
+ #include
+ int main() {
+ int a[1]{ 0 };
+ volatile auto fun = std::for_each_n(a, 1, [](auto b) {});
+ return 0;
+ }"
+ USE_STD_FOR_EACH_N
+ )
+ if(NOT USE_STD_FOR_EACH_N EQUAL 1)
+ set(SEAL_USE_STD_FOR_EACH_N OFF)
+ endif()
+ unset(USE_STD_FOR_EACH_N CACHE)
+ endif()
+
+ cmake_pop_check_state()
+endif()
+
+# Use intrinsics if available
+set(SEAL_USE_INTRIN_OPTION_STR "Use intrinsics")
+option(SEAL_USE_INTRIN ${SEAL_USE_INTRIN_OPTION_STR} ON)
+
+# Check for intrin.h or x64intrin.h
+if(SEAL_USE_INTRIN)
+ if(MSVC)
+ set(SEAL_INTRIN_HEADER "intrin.h")
+ else()
+ set(SEAL_INTRIN_HEADER "x86intrin.h")
+ endif()
+
+ check_include_file_cxx(${SEAL_INTRIN_HEADER} HAVE_INTRIN_HEADER)
+ if(NOT HAVE_INTRIN_HEADER)
+ set(SEAL_USE_INTRIN OFF CACHE BOOL ${SEAL_USE_INTRIN_OPTION_STR} FORCE)
+ endif()
+ unset(HAVE_INTRIN_HEADER CACHE)
+endif()
+
+# Specific intrinsics depending on SEAL_USE_INTRIN
+if(MSVC)
+ set(SEAL_USE__UMUL128_OPTION_STR "Use _umul128")
+ cmake_dependent_option(SEAL_USE__UMUL128 ${SEAL_USE__UMUL128_OPTION_STR} ON "SEAL_USE_INTRIN" OFF)
+
+ set(SEAL_USE__BITSCANREVERSE64_OPTION_STR "Use _BitScanReverse64")
+ cmake_dependent_option(SEAL_USE__BITSCANREVERSE64 ${SEAL_USE__BITSCANREVERSE64_OPTION_STR} ON "SEAL_USE_INTRIN" OFF)
+else()
+ set(SEAL_USE___INT128_OPTION_STR "Use __int128")
+ cmake_dependent_option(SEAL_USE___INT128 ${SEAL_USE___INT128_OPTION_STR} ON "SEAL_USE_INTRIN" OFF)
+
+ set(SEAL_USE___BUILTIN_CLZLL_OPTION_STR "Use __builtin_clzll")
+ cmake_dependent_option(SEAL_USE___BUILTIN_CLZLL ${SEAL_USE___BUILTIN_CLZLL_OPTION_STR} ON "SEAL_USE_INTRIN" OFF)
+endif()
+
+set(SEAL_USE__ADDCARRY_U64_OPTION_STR "Use _addcarry_u64")
+cmake_dependent_option(SEAL_USE__ADDCARRY_U64 ${SEAL_USE__ADDCARRY_U64_OPTION_STR} ON "SEAL_USE_INTRIN" OFF)
+
+set(SEAL_USE__SUBBORROW_U64_OPTION_STR "Use _subborrow_u64")
+cmake_dependent_option(SEAL_USE__SUBBORROW_U64 ${SEAL_USE__SUBBORROW_U64_OPTION_STR} ON "SEAL_USE_INTRIN" OFF)
+
+if(SEAL_USE_INTRIN)
+ cmake_push_check_state(RESET)
+ set(CMAKE_REQUIRED_QUIET TRUE)
+ if(NOT MSVC)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -O0 ${SEAL_LANG_FLAG}")
+ endif()
+
+ if(MSVC)
+ # Check for presence of _umul128
+ if(SEAL_USE__UMUL128)
+ check_cxx_source_runs("
+ #include <${SEAL_INTRIN_HEADER}>
+ int main() {
+ unsigned long long a = 0, b = 0;
+ unsigned long long c;
+ volatile unsigned long long d;
+ d = _umul128(a, b, &c);
+ return 0;
+ }"
+ USE_UMUL128
+ )
+ if(NOT USE_UMUL128 EQUAL 1)
+ set(SEAL_USE__UMUL128 OFF CACHE BOOL ${SEAL_USE__UMUL128_OPTION_STR} FORCE)
+ endif()
+ unset(USE_UMUL128 CACHE)
+ endif()
+
+ # Check for _BitScanReverse64
+ if(SEAL_USE__BITSCANREVERSE64)
+ check_cxx_source_runs("
+ #include <${SEAL_INTRIN_HEADER}>
+ int main() {
+ unsigned long a = 0, b = 0;
+ volatile unsigned char res = _BitScanReverse64(&a, b);
+ return 0;
+ }"
+ USE_BITSCANREVERSE64
+ )
+ if(NOT USE_BITSCANREVERSE64 EQUAL 1)
+ set(SEAL_USE__BITSCANREVERSE64 OFF CACHE BOOL ${SEAL_USE__BITSCANREVERSE64_OPTION_STR} FORCE)
+ endif()
+ unset(USE_BITSCANREVERSE64 CACHE)
+ endif()
+ else()
+ # Check for presence of __int128
+ if(SEAL_USE___INT128)
+ set(CMAKE_EXTRA_INCLUDE_FILES ${SEAL_INTRIN_HEADER})
+ check_type_size("__int128" INT128 LANGUAGE CXX)
+ if(NOT INT128 EQUAL 16)
+ set(SEAL_USE___INT128 OFF CACHE BOOL ${SEAL_USE___INT128_OPTION_STR} FORCE)
+ endif()
+ unset(HAVE_INT128 CACHE)
+ unset(INT128 CACHE)
+ endif()
+
+ # Check for __builtin_clzll
+ if(SEAL_USE___BUILTIN_CLZLL)
+ check_cxx_source_runs("
+ int main() {
+ volatile auto res = __builtin_clzll(0);
+ return 0;
+ }"
+ USE_BUILTIN_CLZLL
+ )
+ if(NOT USE_BUILTIN_CLZLL EQUAL 1)
+ set(SEAL_USE___BUILTIN_CLZLL OFF CACHE BOOL ${SEAL_USE___BUILTIN_CLZLL_OPTION_STR} FORCE)
+ endif()
+ unset(USE_BUILTIN_CLZLL CACHE)
+ endif()
+ endif()
+
+ # Check for _addcarry_u64
+ if(SEAL_USE__ADDCARRY_U64)
+ check_cxx_source_runs("
+ #include <${SEAL_INTRIN_HEADER}>
+ int main() {
+ unsigned long long a;
+ volatile auto res = _addcarry_u64(0,0,0,&a);
+ return 0;
+ }"
+ USE_ADDCARRY_U64
+ )
+ if(NOT USE_ADDCARRY_U64 EQUAL 1)
+ set(SEAL_USE__ADDCARRY_U64 OFF CACHE BOOL ${SEAL_USE__ADDCARRY_U64_OPTION_STR} FORCE)
+ endif()
+ unset(USE_ADDCARRY_U64 CACHE)
+ endif()
+
+ # Check for _subborrow_u64
+ if(SEAL_USE__SUBBORROW_U64)
+ check_cxx_source_runs("
+ #include <${SEAL_INTRIN_HEADER}>
+ int main() {
+ unsigned long long a;
+ volatile auto res = _subborrow_u64(0,0,0,&a);
+ return 0;
+ }"
+ USE_SUBBORROW_U64
+ )
+ if(NOT USE_SUBBORROW_U64 EQUAL 1)
+ set(SEAL_USE__SUBBORROW_U64 OFF CACHE BOOL ${SEAL_USE__SUBBORROW_U64_OPTION_STR} FORCE)
+ endif()
+ unset(USE_SUBBORROW_U64 CACHE)
+ endif()
+
+ cmake_pop_check_state()
+endif()
+
+# Create an object library to compile sources only once
+add_library(seal_obj OBJECT)
+
+# Add source files to library and header files to install
+add_subdirectory(native/src/seal)
+
+# Set C++ language version and include directories for the object library
+set_language(seal_obj)
+set_include_directories(seal_obj)
+
+if(SEAL_USE_MSGSL AND NOT MSVC)
+ target_link_libraries(seal_obj PRIVATE GSL)
+endif()
+
+if(SEAL_USE_ZLIB AND NOT MSVC)
+ target_link_libraries(seal_obj PRIVATE zlibstatic)
+endif()
+
+# Always build the static library
+add_library(seal STATIC $)
+set_version(seal)
+set_version_filename(seal)
+set_language(seal)
+set_include_directories(seal)
+link_threads(seal)
+install_target(seal SEALTargets)
+
+# Conditionally add MSGSL include directory to build interface
+if(SEAL_USE_MSGSL AND NOT MSVC)
+ target_include_directories(seal PUBLIC $)
+endif()
+
+# Conditionally build the shared library
+if(BUILD_SHARED_LIBS)
+ add_library(seal_shared SHARED $)
+ set_target_properties(seal_shared PROPERTIES OUTPUT_NAME seal)
+ set_version(seal_shared)
+ set_soversion(seal_shared)
+ set_language(seal_shared)
+ set_include_directories(seal_shared)
+ link_threads(seal_shared)
+
+ # Conditionally add MSGSL include directory to build interface
+ if(SEAL_USE_MSGSL AND NOT MSVC)
+ target_include_directories(seal_shared PUBLIC $)
+ endif()
+
+ if(SEAL_USE_ZLIB AND NOT MSVC)
+ # In the shared build we link zlibstatic into the shared library
+ target_link_libraries(seal_shared PRIVATE zlibstatic)
+ endif()
+
+ install_target(seal_shared SEALTargets)
+endif()
+
+# In UNIX-like platforms combine manually seal and zlibstatic into a single archive; not pretty, but works
+if(SEAL_USE_ZLIB AND NOT MSVC)
+ if(CMAKE_HOST_WIN32)
+ get_filename_component(CXX_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY)
+ set(AR_CMD_PATH "${CXX_DIR}/llvm-ar.exe")
+ file(TO_NATIVE_PATH "${AR_CMD_PATH}" AR_CMD_PATH)
+ set(DEL_CMD "del")
+ set(DEL_CMD_OPTS "")
+ else()
+ set(AR_CMD_PATH "ar")
+ set(DEL_CMD "rm")
+ set(DEL_CMD_OPTS "-rf")
+ endif()
+ file(COPY "${zlibstatic_LIBRARY_PATH}" DESTINATION "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
+ add_custom_command(TARGET seal POST_BUILD
+ COMMAND "${AR_CMD_PATH}" x $
+ COMMAND "${AR_CMD_PATH}" x $/libz.a
+ COMMAND "${AR_CMD_PATH}" rcs $ *.o
+ COMMAND ${DEL_CMD} ${DEL_CMD_OPTS} *.o
+ WORKING_DIRECTORY $)
+endif()
+
+#########################
+# SEAL C export library #
+#########################
+
+# Check that size_t is 8 bytes
+include(CheckTypeSize)
+check_type_size("size_t" SIZET LANGUAGE C)
+
+set(SEAL_BUILD_SEAL_C_OPTION_STR "Build C export library for Microsoft SEAL")
+cmake_dependent_option(SEAL_BUILD_SEAL_C ${SEAL_BUILD_SEAL_C_OPTION_STR} OFF "${SIZET} EQUAL 8" OFF)
+
+unset(SIZET CACHE)
+unset(HAVE_SIZET CACHE)
+
+# Create shared SEAL_C library but add no source files yet
+if(SEAL_BUILD_SEAL_C)
+ add_library(sealc SHARED)
+
+ # Add source files to library and header files to install
+ add_subdirectory(native/src/seal/c)
+ set_version(sealc)
+ set_soversion(sealc)
+ set_language(sealc)
+ set_include_directories(sealc)
+
+ target_link_libraries(sealc PUBLIC seal)
+
+ install_target(sealc SEALTargets)
+endif()
+
+#################################
+# Installation and CMake config #
+#################################
+
+# Create the CMake config file
+include(CMakePackageConfigHelpers)
+configure_package_config_file(
+ ${SEAL_CONFIG_IN_FILENAME} ${SEAL_CONFIG_FILENAME}
+ INSTALL_DESTINATION ${SEAL_CONFIG_INSTALL_DIR})
+
+# Install the export
+install(
+ EXPORT SEALTargets
+ NAMESPACE SEAL::
+ DESTINATION ${SEAL_CONFIG_INSTALL_DIR})
+
+# Version file; we require exact version match for downstream
+write_basic_package_version_file(
+ ${SEAL_CONFIG_VERSION_FILENAME}
+ VERSION ${SEAL_VERSION}
+ COMPATIBILITY SameMinorVersion)
+
+# Install config and module files
+install(
+ FILES
+ ${SEAL_CONFIG_FILENAME}
+ ${SEAL_CONFIG_VERSION_FILENAME}
+ DESTINATION ${SEAL_CONFIG_INSTALL_DIR})
+
+# We export SEALTargets from the build tree so it can be used by other projects
+# without requiring an install.
+export(
+ EXPORT SEALTargets
+ NAMESPACE SEAL::
+ FILE ${SEAL_TARGETS_FILENAME})
+
+# In UNIX-like platforms install MSGSL header files
+if(SEAL_USE_MSGSL AND NOT MSVC)
+ install(
+ DIRECTORY
+ ${MSGSL_INCLUDE_DIR}/gsl
+ DESTINATION
+ ${SEAL_INCLUDES_INSTALL_DIR}
+ )
+endif()
+
+#####################
+# SEAL C++ examples #
+#####################
+
+# [option] SEAL_BUILD_EXAMPLES
+set(SEAL_BUILD_EXAMPLES_OPTION_STR "Build C++ examples for Microsoft SEAL")
+option(SEAL_BUILD_EXAMPLES ${SEAL_BUILD_EXAMPLES_OPTION_STR} OFF)
+
+if(SEAL_BUILD_EXAMPLES)
+ add_executable(sealexamples)
+ add_subdirectory(native/examples)
+ add_subdirectory(native/examples/hello)
+ add_subdirectory(native/examples/generic)
+ #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)
+endif()
+
+##################
+# SEAL C++ tests #
+##################
+
+# [option] SEAL_BUILD_TESTS
+set(SEAL_BUILD_TESTS_OPTION_STR "Build C++ tests for Microsoft SEAL")
+option(SEAL_BUILD_TESTS ${SEAL_BUILD_TESTS_OPTION_STR} OFF)
+
+if(SEAL_BUILD_TESTS)
+ add_executable(sealtest)
+ add_subdirectory(native/tests/seal)
+ target_link_libraries(sealtest PRIVATE seal gtest)
+endif()
+
+#######################################
+# Configure SEALNet and NuGet package #
+#######################################
+
+# Set the sealc dynamic library file names to be included in creating
+# the NuGet package. When building a multi-platform NuGet package, the
+# dynamic library paths need to be specified explicitly in the NuGet
+# command. See dotnet/nuget/SEALNet.nuspec.in.
+
+# First create the multi-platform NuSpec file so disable all platform-specific
+# library paths
+unset(SEAL_WINDOWS_SEAL_C_PATH)
+unset(SEAL_LINUX_SEAL_C_PATH)
+unset(SEAL_MACOS_SEAL_C_PATH)
+
+# Create SEALNet-multi.nuspec for a multi-platform NuGet package
+configure_file(
+ ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet-multi.nuspec.in
+ ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet-multi.nuspec
+ @ONLY)
+
+set(SEAL_WINDOWS_SEAL_C_PATH ${SEAL_SOURCE_DIR}/lib/x64/$Configuration$/sealc.dll)
+set(SEAL_LINUX_SEAL_C_PATH ${SEAL_SOURCE_DIR}/lib/libsealc.so)
+set(SEAL_MACOS_SEAL_C_PATH ${SEAL_SOURCE_DIR}/lib/libsealc.dylib)
+
+# Supporting local building of NuGet package
+if(MSVC)
+ set(NUGET_SEAL_C_PATH ${SEAL_WINDOWS_SEAL_C_PATH})
+elseif(UNIX)
+ set(NUGET_SEAL_C_PATH ${SEAL_LINUX_SEAL_C_PATH})
+elseif(APPLE)
+ set(NUGET_SEAL_C_PATH ${SEAL_MACOS_SEAL_C_PATH})
+endif()
+
+if(NUGET_SEAL_C_PATH)
+ # Create SEALNet.nuspec for a local NuGet pack from SEALNet.nuspec.in
+ configure_file(
+ ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.nuspec.in
+ ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.nuspec
+ @ONLY)
+endif()
+
+# Create SEALNet.targets from SEALNet.targets.in
+configure_file(
+ ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.targets.in
+ ${SEAL_SOURCE_DIR}/dotnet/nuget/SEALNet.targets
+ @ONLY)
diff --git a/bigpiseal3.5.1/CODE_OF_CONDUCT.md b/bigpiseal3.5.1/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000000000000000000000000000000000..f9ba8cf65f3e3104dd061c178066ec8247811f33
--- /dev/null
+++ b/bigpiseal3.5.1/CODE_OF_CONDUCT.md
@@ -0,0 +1,9 @@
+# Microsoft Open Source Code of Conduct
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+
+Resources:
+
+- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
+- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
+- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
diff --git a/bigpiseal3.5.1/CONTRIBUTING.md b/bigpiseal3.5.1/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..ca8c450ec03469445d22a828101b0eca8b35114e
--- /dev/null
+++ b/bigpiseal3.5.1/CONTRIBUTING.md
@@ -0,0 +1,25 @@
+# Contributing
+
+This project welcomes contributions and suggestions.
+Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution.
+For details, visit https://cla.opensource.microsoft.com.
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/).
+Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) for any additional questions or comments.
+
+### Pull Requests
+
+Submit pull requrests to **branch *contrib***.
+Pull requests to any other branch will not be accepted.
+
+When you submit a pull request, a CLA bot will automatically determine whether you need to **provide a CLA** and decorate the PR appropriately (e.g., status check, comment).
+Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
+
+### Formatting
+
+Microsoft SEAL uses a customized `.clang-format` configuration for C++ code styling.
+A script `tools/scripts/clang-format-all.sh` is provided to easily format all C++ sources and headers in the `native` directory.
+
+Documentation are mostly written in GitHub-flavored Markdown.
+A line break is required after each full sentence.
\ No newline at end of file
diff --git a/bigpiseal3.5.1/ISSUES.md b/bigpiseal3.5.1/ISSUES.md
new file mode 100644
index 0000000000000000000000000000000000000000..b5cc00412913fc3a7f528434632dc8695acff881
--- /dev/null
+++ b/bigpiseal3.5.1/ISSUES.md
@@ -0,0 +1,29 @@
+# Issues
+
+## Technical questions
+
+The best way to get help with technical questions is on
+[StackOverflow](https://stackoverflow.com/questions/tagged/seal) using the `[seal]`
+tag. To contact the Microsoft SEAL team directly, please email
+[sealcrypto@microsoft.com](mailto:sealcrypto@microsoft.com).
+
+## Bug reports
+
+We appreciate community efforts to find and fix bugs and issues in Microsoft SEAL.
+If you believe you have found a bug or want to report some other issue, please
+do so on [GitHub](https://github.com/Microsoft/SEAL/issues). To help others
+determine what the problem may be, we provide a helpful script that collects
+relevant system information that you can submit with the bug report (see below).
+
+### System information
+
+To collect system information for an improved bug report, please run
+```
+make -C tools system_info
+```
+This will result in a file `system_info.tar.gz` to be generated, which you can
+optionally attach with your bug report.
+
+## Critical security issues
+
+For reporting critical security issues, see [SECURITY.md](SECURITY.md).
diff --git a/bigpiseal3.5.1/LICENSE b/bigpiseal3.5.1/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..21071075c24599ee98254f702bcfc504cdc275a6
--- /dev/null
+++ b/bigpiseal3.5.1/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/bigpiseal3.5.1/NOTICE b/bigpiseal3.5.1/NOTICE
new file mode 100644
index 0000000000000000000000000000000000000000..6ace895c31d9b58d7ced493431d29da7a064089a
--- /dev/null
+++ b/bigpiseal3.5.1/NOTICE
@@ -0,0 +1,2 @@
+This software uses the BLAKE2 library (https://github.com/BLAKE2/BLAKE2)
+The BLAKE2 library is licensed under CC0 Universal, version 1.0. You can find a copy of this license at https://creativecommons.org/publicdomain/zero/1.0/legalcode
diff --git a/bigpiseal3.5.1/SEAL.sln b/bigpiseal3.5.1/SEAL.sln
new file mode 100644
index 0000000000000000000000000000000000000000..66759e7fd520dba9f55252f24324d427c28e7b94
--- /dev/null
+++ b/bigpiseal3.5.1/SEAL.sln
@@ -0,0 +1,189 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29215.179
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEAL", "native\src\SEAL.vcxproj", "{7EA96C25-FC0D-485A-BB71-32B6DA55652A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEALTest", "native\tests\SEALTest.vcxproj", "{0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {7EA96C25-FC0D-485A-BB71-32B6DA55652A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEALExamples", "native\examples\SEALExamples.vcxproj", "{2B57D847-26DC-45FF-B9AF-EE33910B5093}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {7EA96C25-FC0D-485A-BB71-32B6DA55652A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SEAL_C", "native\src\SEAL_C.vcxproj", "{70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {7EA96C25-FC0D-485A-BB71-32B6DA55652A}
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SEALNet", "dotnet\src\SEALNet.csproj", "{D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D} = {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SEALNetTest", "dotnet\tests\SEALNetTest.csproj", "{D0FCCA29-F0F8-49A3-9615-24FF899F1909}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E} = {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SEALNetExamples", "dotnet\examples\SEALNetExamples.csproj", "{18DA9F90-3131-461A-A3E8-40AC0B1D7632}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "native", "native", "{A5BADDF0-1F03-48FE-AAC0-3355614C9A8D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{0786F255-C3A7-4912-A669-12273E7AE013}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{33C15AAC-6E56-477E-A118-3451FD21AC49}"
+ ProjectSection(SolutionItems) = preProject
+ dotnet\nuget\NUGET.md = dotnet\nuget\NUGET.md
+ dotnet\nuget\SEALNet.nuspec.in = dotnet\nuget\SEALNet.nuspec.in
+ dotnet\nuget\SEALNet.targets.in = dotnet\nuget\SEALNet.targets.in
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C73A600E-7F50-467C-9228-58AC2C1A7DDA}"
+ ProjectSection(SolutionItems) = preProject
+ .clang-format = .clang-format
+ .gitignore = .gitignore
+ CHANGES.md = CHANGES.md
+ CMakeLists.txt = CMakeLists.txt
+ CODE_OF_CONDUCT.md = CODE_OF_CONDUCT.md
+ CONTRIBUTING.md = CONTRIBUTING.md
+ ISSUES.md = ISSUES.md
+ LICENSE = LICENSE
+ NOTICE = NOTICE
+ README.md = README.md
+ SECURITY.md = SECURITY.md
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "thirdparty", "thirdparty", "{6B00D0DE-8A17-44B8-BF47-F372E9189434}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "zlib", "zlib", "{5E524D23-AD60-45AF-B279-0322941E9F31}"
+ ProjectSection(SolutionItems) = preProject
+ thirdparty\zlib\CMakeLists.txt = thirdparty\zlib\CMakeLists.txt
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "msgsl", "msgsl", "{B4EF7358-C76B-4142-9746-B082114B1DDD}"
+ ProjectSection(SolutionItems) = preProject
+ thirdparty\msgsl\CMakeLists.txt = thirdparty\msgsl\CMakeLists.txt
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "googletest", "googletest", "{0DD76E94-59E1-49D4-9ED7-8C696B89F26E}"
+ ProjectSection(SolutionItems) = preProject
+ thirdparty\googletest\CMakeLists.txt = thirdparty\googletest\CMakeLists.txt
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cmake", "cmake", "{256C7291-7A4D-466A-BF88-535B541D2CAC}"
+ ProjectSection(SolutionItems) = preProject
+ cmake\SEALConfig.cmake.in = cmake\SEALConfig.cmake.in
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{03B08661-29E2-4806-9F10-F1B7013D717D}"
+ ProjectSection(SolutionItems) = preProject
+ pipelines\jobs.yml = pipelines\jobs.yml
+ pipelines\nix.yml = pipelines\nix.yml
+ pipelines\nuget.yml = pipelines\nuget.yml
+ pipelines\pipeline-CI-Debug-Linux.yml = pipelines\pipeline-CI-Debug-Linux.yml
+ pipelines\pipeline-CI-Debug-macOS.yml = pipelines\pipeline-CI-Debug-macOS.yml
+ pipelines\pipeline-CI-Debug-Windows.yml = pipelines\pipeline-CI-Debug-Windows.yml
+ pipelines\pipeline-CI-Release-All.yml = pipelines\pipeline-CI-Release-All.yml
+ pipelines\pipeline-NuGet.yml = pipelines\pipeline-NuGet.yml
+ pipelines\pipeline-PR-Debug-All.yml = pipelines\pipeline-PR-Debug-All.yml
+ pipelines\windows.yml = pipelines\windows.yml
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|Win32.Build.0 = Debug|Win32
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|x64.ActiveCfg = Debug|x64
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Debug|x64.Build.0 = Debug|x64
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|Win32.ActiveCfg = Release|Win32
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|Win32.Build.0 = Release|Win32
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|x64.ActiveCfg = Release|x64
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A}.Release|x64.Build.0 = Release|x64
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|Win32.Build.0 = Debug|Win32
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|x64.ActiveCfg = Debug|x64
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Debug|x64.Build.0 = Debug|x64
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|Win32.ActiveCfg = Release|Win32
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|Win32.Build.0 = Release|Win32
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|x64.ActiveCfg = Release|x64
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF}.Release|x64.Build.0 = Release|x64
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|Win32.Build.0 = Debug|Win32
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|x64.ActiveCfg = Debug|x64
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Debug|x64.Build.0 = Debug|x64
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|Win32.ActiveCfg = Release|Win32
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|Win32.Build.0 = Release|Win32
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|x64.ActiveCfg = Release|x64
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093}.Release|x64.Build.0 = Release|x64
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|Win32.Build.0 = Debug|Win32
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|x64.ActiveCfg = Debug|x64
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Debug|x64.Build.0 = Debug|x64
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|Win32.ActiveCfg = Release|Win32
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|Win32.Build.0 = Release|Win32
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|x64.ActiveCfg = Release|x64
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D}.Release|x64.Build.0 = Release|x64
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|Win32.Build.0 = Debug|Any CPU
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Debug|x64.Build.0 = Debug|Any CPU
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|Win32.ActiveCfg = Release|Any CPU
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|Win32.Build.0 = Release|Any CPU
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|x64.ActiveCfg = Release|Any CPU
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E}.Release|x64.Build.0 = Release|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|Win32.Build.0 = Debug|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Debug|x64.Build.0 = Debug|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|Win32.ActiveCfg = Release|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|Win32.Build.0 = Release|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|x64.ActiveCfg = Release|Any CPU
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909}.Release|x64.Build.0 = Release|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|Win32.Build.0 = Debug|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Debug|x64.Build.0 = Debug|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|Win32.ActiveCfg = Release|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|Win32.Build.0 = Release|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|x64.ActiveCfg = Release|Any CPU
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632}.Release|x64.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {7EA96C25-FC0D-485A-BB71-32B6DA55652A} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D}
+ {0345DC4D-EFE3-460E-AB7E-AA6E05BB8DFF} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D}
+ {2B57D847-26DC-45FF-B9AF-EE33910B5093} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D}
+ {70BBB2AA-FA77-40C1-890F-7AA7DBB3AD3D} = {A5BADDF0-1F03-48FE-AAC0-3355614C9A8D}
+ {D7ED94EC-3FAB-4B87-AB5F-0308EA92520E} = {0786F255-C3A7-4912-A669-12273E7AE013}
+ {D0FCCA29-F0F8-49A3-9615-24FF899F1909} = {0786F255-C3A7-4912-A669-12273E7AE013}
+ {18DA9F90-3131-461A-A3E8-40AC0B1D7632} = {0786F255-C3A7-4912-A669-12273E7AE013}
+ {33C15AAC-6E56-477E-A118-3451FD21AC49} = {0786F255-C3A7-4912-A669-12273E7AE013}
+ {6B00D0DE-8A17-44B8-BF47-F372E9189434} = {C73A600E-7F50-467C-9228-58AC2C1A7DDA}
+ {5E524D23-AD60-45AF-B279-0322941E9F31} = {6B00D0DE-8A17-44B8-BF47-F372E9189434}
+ {B4EF7358-C76B-4142-9746-B082114B1DDD} = {6B00D0DE-8A17-44B8-BF47-F372E9189434}
+ {0DD76E94-59E1-49D4-9ED7-8C696B89F26E} = {6B00D0DE-8A17-44B8-BF47-F372E9189434}
+ {256C7291-7A4D-466A-BF88-535B541D2CAC} = {C73A600E-7F50-467C-9228-58AC2C1A7DDA}
+ {03B08661-29E2-4806-9F10-F1B7013D717D} = {C73A600E-7F50-467C-9228-58AC2C1A7DDA}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {15A17F22-F747-4B82-BF5F-E0224AF4B3ED}
+ EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
+EndGlobal
diff --git a/bigpiseal3.5.1/SECURITY.md b/bigpiseal3.5.1/SECURITY.md
new file mode 100644
index 0000000000000000000000000000000000000000..e0dfff56a9569fee0ec4628bb42319f81731b250
--- /dev/null
+++ b/bigpiseal3.5.1/SECURITY.md
@@ -0,0 +1,41 @@
+
+
+## Security
+
+Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
+
+If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
+
+## Reporting Security Issues
+
+**Please do not report security vulnerabilities through public GitHub issues.**
+
+Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
+
+If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
+
+You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
+
+Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
+
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
+ * Full paths of source file(s) related to the manifestation of the issue
+ * The location of the affected source code (tag/branch/commit or direct URL)
+ * Any special configuration required to reproduce the issue
+ * Step-by-step instructions to reproduce the issue
+ * Proof-of-concept or exploit code (if possible)
+ * Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Policy
+
+Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
+
+
diff --git a/bigpiseal3.5.1/android/.gitignore b/bigpiseal3.5.1/android/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..603b14077394cd2294ac6922fe619669630ef3ab
--- /dev/null
+++ b/bigpiseal3.5.1/android/.gitignore
@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
diff --git a/bigpiseal3.5.1/android/app/.gitignore b/bigpiseal3.5.1/android/app/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/bigpiseal3.5.1/android/app/build.gradle b/bigpiseal3.5.1/android/app/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..ce44320a98507c0f9d859a652bd7d1218d925d58
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/build.gradle
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.3"
+ defaultConfig {
+ applicationId "com.microsoft.seal"
+ minSdkVersion 24
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ externalNativeBuild {
+ cmake {
+ cppFlags ""
+ arguments "-DSEAL_BUILD_SEAL_C=1",
+ "-DSEAL_USE_INTRIN=0"
+ }
+ }
+ ndk {
+ abiFilters 'x86_64'
+ abiFilters 'arm64-v8a'
+ }
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ externalNativeBuild {
+ cmake {
+ path "../../CMakeLists.txt"
+ version "3.12.0+"
+ }
+ }
+ ndkVersion "21.0.6113669"
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+}
diff --git a/bigpiseal3.5.1/android/app/proguard-rules.pro b/bigpiseal3.5.1/android/app/proguard-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..cb446e5802c1891b291de2390644515620e3f9aa
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/proguard-rules.pro
@@ -0,0 +1,24 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT license.
+
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/bigpiseal3.5.1/android/app/src/main/AndroidManifest.xml b/bigpiseal3.5.1/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..03f4660430236c555b66f94f92233c4a58532f10
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/bigpiseal3.5.1/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/bigpiseal3.5.1/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1f6bb290603d7caa16c5fb6f61bbfdc750622f5c
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bigpiseal3.5.1/android/app/src/main/res/drawable/ic_launcher_background.xml b/bigpiseal3.5.1/android/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d025f9bf6b67c63044a36a9ff44fbc69e5c5822
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..898f3ed59ac9f3248734a00e5902736c9367d455
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000000000000000000000000000000000000..dffca3601eba7bf5f409bdd520820e2eb5122c75
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..64ba76f75e9ce021aa3d95c213491f73bcacb597
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000000000000000000000000000000000000..dae5e082342fcdeee5db8a6e0b27028e2d2808f5
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5ed46597ea8447d91ab1786a34e30f1c26b18bd
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000000000000000000000000000000000..14ed0af35023e4f1901cf03487b6c524257b8483
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..b0907cac3bfd8fbfdc46e1108247f0a1055387ec
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000000000000000000000000000000000..d8ae03154975f397f8ed1b84f2d4bf9783ecfa26
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..2c18de9e66108411737e910f5c1972476f03ddbf
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000000000000000000000000000000000..beed3cdd2c32af5114a7dc70b9ef5b698eb8797e
Binary files /dev/null and b/bigpiseal3.5.1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/bigpiseal3.5.1/android/app/src/main/res/values/colors.xml b/bigpiseal3.5.1/android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4af7e66858725b1387c4d84047793e1e3f9fd2bb
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/bigpiseal3.5.1/android/app/src/main/res/values/strings.xml b/bigpiseal3.5.1/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..695102d90d71516ad4ccc8927e97f4160f82c635
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ SEAL
+
diff --git a/bigpiseal3.5.1/android/app/src/main/res/values/styles.xml b/bigpiseal3.5.1/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8873a554aa97974f85e80b3d3ca36811c9194481
--- /dev/null
+++ b/bigpiseal3.5.1/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/bigpiseal3.5.1/android/build.gradle b/bigpiseal3.5.1/android/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..53c02c8db8574603f89a4267167893897dfe6a04
--- /dev/null
+++ b/bigpiseal3.5.1/android/build.gradle
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ google()
+ jcenter()
+
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.6.2'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/bigpiseal3.5.1/android/gradle.properties b/bigpiseal3.5.1/android/gradle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e4bbb28b9558f1606a4630bbf372ae25eaec6b13
--- /dev/null
+++ b/bigpiseal3.5.1/android/gradle.properties
@@ -0,0 +1,23 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT license.
+
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
diff --git a/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.jar b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..f6b961fd5a86aa5fbfe90f707c3138408be7c718
Binary files /dev/null and b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.properties b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..8a68daf59cb8845e8bceac29d74cc1204ac6c832
--- /dev/null
+++ b/bigpiseal3.5.1/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,9 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT license.
+
+#Mon Apr 06 10:08:19 PDT 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/bigpiseal3.5.1/android/gradlew b/bigpiseal3.5.1/android/gradlew
new file mode 100644
index 0000000000000000000000000000000000000000..cccdd3d517fc5249beaefa600691cf150f2fa3e6
--- /dev/null
+++ b/bigpiseal3.5.1/android/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/bigpiseal3.5.1/android/gradlew.bat b/bigpiseal3.5.1/android/gradlew.bat
new file mode 100644
index 0000000000000000000000000000000000000000..f9553162f122c71b34635112e717c3e733b5b212
--- /dev/null
+++ b/bigpiseal3.5.1/android/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/bigpiseal3.5.1/android/settings.gradle b/bigpiseal3.5.1/android/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..983cef286040c01a6ab5565d8085a49fe27ad664
--- /dev/null
+++ b/bigpiseal3.5.1/android/settings.gradle
@@ -0,0 +1,5 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+include ':app'
+rootProject.name='SEAL'
diff --git a/bigpiseal3.5.1/cmake/SEALConfig.cmake.in b/bigpiseal3.5.1/cmake/SEALConfig.cmake.in
new file mode 100644
index 0000000000000000000000000000000000000000..b13a1d1d712838cca6b26aff82ba44909a3951d4
--- /dev/null
+++ b/bigpiseal3.5.1/cmake/SEALConfig.cmake.in
@@ -0,0 +1,101 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT license.
+
+# Exports target SEAL::seal
+#
+# Creates variables:
+# SEAL_FOUND : If a static Microsoft SEAL library was found
+# SEAL_SHARED_FOUND : If a shared Microsoft SEAL library was found
+# SEAL_C_FOUND : If a Microsoft SEAL C export library was found
+# SEAL_VERSION : The full version number
+# SEAL_VERSION_MAJOR : The major version number
+# SEAL_VERSION_MINOR : The minor version number
+# SEAL_VERSION_PATCH : The patch version number
+# SEAL_DEBUG : Set to non-zero value if library is compiled with extra debugging code (very slow!)
+# SEAL_USE_CXX17 : Set to non-zero value if library is compiled as C++17 instead of C++14
+# SEAL_ENFORCE_HE_STD_SECURITY : Set to non-zero value if library is compiled to enforce at least
+# a 128-bit security level based on HomomorphicEncryption.org security estimates
+# SEAL_USE_MSGSL : Set to non-zero value if library is compiled with Microsoft GSL support
+# SEAL_USE_ZLIB : Set to non-zero value if library is compiled with zlib support
+
+@PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+
+macro(warning_when_not_quiet msg)
+ if(NOT SEAL_FIND_QUIETLY)
+ message(WARNING ${msg})
+ endif()
+endmacro()
+
+macro(status_when_not_quiet msg)
+ if(NOT SEAL_FIND_QUIETLY)
+ message(STATUS ${msg})
+ endif()
+endmacro()
+
+macro(find_seal_dependency dep)
+ find_dependency(${dep})
+ if(NOT ${dep}_FOUND)
+ warning_when_not_quiet("Could not find dependency `${dep}` required by this configuration")
+ set(SEAL_FOUND FALSE)
+ return()
+ endif()
+endmacro()
+
+set(SEAL_FOUND FALSE)
+set(SEAL_SHARED_FOUND FALSE)
+set(SEAL_C_FOUND FALSE)
+
+set(SEAL_VERSION @SEAL_VERSION@)
+set(SEAL_VERSION_MAJOR @SEAL_VERSION_MAJOR@)
+set(SEAL_VERSION_MINOR @SEAL_VERSION_MINOR@)
+set(SEAL_VERSION_PATCH @SEAL_VERSION_PATCH@)
+
+set(SEAL_BUILD_TYPE @CMAKE_BUILD_TYPE@)
+set(SEAL_DEBUG @SEAL_DEBUG@)
+set(SEAL_USE_CXX17 @SEAL_USE_CXX17@)
+set(SEAL_ENFORCE_HE_STD_SECURITY @SEAL_ENFORCE_HE_STD_SECURITY@)
+
+set(SEAL_USE_MSGSL @SEAL_USE_MSGSL@)
+set(SEAL_USE_ZLIB @SEAL_USE_ZLIB@)
+
+# Add the current directory to the module search path
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
+
+set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+set(THREADS_PREFER_PTHREAD_FLAG TRUE)
+find_seal_dependency(Threads)
+
+include(${CMAKE_CURRENT_LIST_DIR}/SEALTargets.cmake)
+
+if(TARGET SEAL::seal)
+ set(SEAL_FOUND TRUE)
+endif()
+
+if(TARGET SEAL::seal_shared)
+ set(SEAL_SHARED_FOUND TRUE)
+endif()
+
+if(TARGET SEAL::sealc)
+ set(SEAL_C_FOUND TRUE)
+endif()
+
+if(SEAL_FOUND)
+ status_when_not_quiet("Microsoft SEAL -> Version ${SEAL_VERSION} detected")
+ if(SEAL_DEBUG)
+ status_when_not_quiet("Performance warning: Microsoft SEAL compiled in debug mode")
+ endif()
+
+ set(SEAL_TARGETS_AVAILABLE "Microsoft SEAL -> Targets available: SEAL::seal")
+ if(SEAL_SHARED_FOUND)
+ string(APPEND SEAL_TARGETS_AVAILABLE ", SEAL::seal_shared")
+ endif()
+ if(SEAL_C_FOUND)
+ string(APPEND SEAL_TARGETS_AVAILABLE ", SEAL::sealc")
+ endif()
+
+ status_when_not_quiet(${SEAL_TARGETS_AVAILABLE})
+else()
+ warning_when_not_quiet("Microsoft SEAL -> NOT FOUND")
+endif()
diff --git a/bigpiseal3.5.1/dotnet/examples/1_BFV_Basics.cs b/bigpiseal3.5.1/dotnet/examples/1_BFV_Basics.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8a1834210bec4f58dddc45302e838191df4ef67c
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/1_BFV_Basics.cs
@@ -0,0 +1,447 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using Microsoft.Research.SEAL;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ private static void ExampleBFVBasics()
+ {
+ Utilities.PrintExampleBanner("Example: BFV Basics");
+
+ /*
+ In this example, we demonstrate performing simple computations (a polynomial
+ evaluation) on encrypted integers using the BFV encryption scheme.
+
+ The first task is to set up an instance of the EncryptionParameters class.
+ It is critical to understand how the different parameters behave, how they
+ affect the encryption scheme, performance, and the security level. There are
+ three encryption parameters that are necessary to set:
+
+ - PolyModulusDegree (degree of polynomial modulus);
+ - CoeffModulus ([ciphertext] coefficient modulus);
+ - PlainModulus (plaintext modulus; only for the BFV scheme).
+
+ The BFV scheme cannot perform arbitrary computations on encrypted data.
+ Instead, each ciphertext has a specific quantity called the `invariant noise
+ budget' -- or `noise budget' for short -- measured in bits. The noise budget
+ in a freshly encrypted ciphertext (initial noise budget) is determined by
+ the encryption parameters. Homomorphic operations consume the noise budget
+ at a rate also determined by the encryption parameters. In BFV the two basic
+ operations allowed on encrypted data are additions and multiplications, of
+ which additions can generally be thought of as being nearly free in terms of
+ noise budget consumption compared to multiplications. Since noise budget
+ consumption compounds in sequential multiplications, the most significant
+ factor in choosing appropriate encryption parameters is the multiplicative
+ depth of the arithmetic circuit that the user wants to evaluate on encrypted
+ data. Once the noise budget of a ciphertext reaches zero it becomes too
+ corrupted to be decrypted. Thus, it is essential to choose the parameters to
+ be large enough to support the desired computation; otherwise the result is
+ impossible to make sense of even with the secret key.
+ */
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+
+ /*
+ The first parameter we set is the degree of the `polynomial modulus'. This
+ must be a positive power of 2, representing the degree of a power-of-two
+ cyclotomic polynomial; it is not necessary to understand what this means.
+
+ Larger PolyModulusDegree makes ciphertext sizes larger and all operations
+ slower, but enables more complicated encrypted computations. Recommended
+ values are 1024, 2048, 4096, 8192, 16384, 32768, but it is also possible
+ to go beyond this range.
+
+ In this example we use a relatively small polynomial modulus. Anything
+ smaller than this will enable only very restricted encrypted computations.
+ */
+ ulong polyModulusDegree = 4096;
+ parms.PolyModulusDegree = polyModulusDegree;
+
+ /*
+ Next we set the [ciphertext] `coefficient modulus' (CoeffModulus). This
+ parameter is a large integer, which is a product of distinct prime numbers,
+ numbers, each represented by an instance of the Modulus class. The
+ bit-length of CoeffModulus means the sum of the bit-lengths of its prime
+ factors.
+
+ A larger CoeffModulus implies a larger noise budget, hence more encrypted
+ computation capabilities. However, an upper bound for the total bit-length
+ of the CoeffModulus is determined by the PolyModulusDegree, as follows:
+
+ +----------------------------------------------------+
+ | PolyModulusDegree | max CoeffModulus bit-length |
+ +---------------------+------------------------------+
+ | 1024 | 27 |
+ | 2048 | 54 |
+ | 4096 | 109 |
+ | 8192 | 218 |
+ | 16384 | 438 |
+ | 32768 | 881 |
+ +---------------------+------------------------------+
+
+ These numbers can also be found in native/src/seal/util/hestdparms.h encoded
+ in the function SEAL_HE_STD_PARMS_128_TC, and can also be obtained from the
+ function
+
+ CoeffModulus.MaxBitCount(polyModulusDegree).
+
+ For example, if PolyModulusDegree is 4096, the coeff_modulus could consist
+ of three 36-bit primes (108 bits).
+
+ Microsoft SEAL comes with helper functions for selecting the CoeffModulus.
+ For new users the easiest way is to simply use
+
+ CoeffModulus.BFVDefault(polyModulusDegree),
+
+ which returns IEnumerable consisting of a generally good choice
+ for the given PolyModulusDegree.
+ */
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+
+ /*
+ The plaintext modulus can be any positive integer, even though here we take
+ it to be a power of two. In fact, in many cases one might instead want it
+ to be a prime number; we will see this in later examples. The plaintext
+ modulus determines the size of the plaintext data type and the consumption
+ of noise budget in multiplications. Thus, it is essential to try to keep the
+ plaintext data type as small as possible for best performance. The noise
+ budget in a freshly encrypted ciphertext is
+
+ ~ log2(CoeffModulus/PlainModulus) (bits)
+
+ and the noise budget consumption in a homomorphic multiplication is of the
+ form log2(PlainModulus) + (other terms).
+
+ The plaintext modulus is specific to the BFV scheme, and cannot be set when
+ using the CKKS scheme.
+ */
+ parms.PlainModulus = new Modulus(1024);
+
+ /*
+ Now that all parameters are set, we are ready to construct a SEALContext
+ object. This is a heavy class that checks the validity and properties of the
+ parameters we just set.
+
+ C# 8.0 introduced the `using` declaration for local variables. This is a very
+ convenient addition to the language: it causes the Dispose method for the
+ object to be called at the end of the enclosing scope (in this case the end
+ of this function), hence automatically releasing the native resources held by
+ the object. This is helpful, because releasing the native resources returns
+ the allocated memory to the memory pool, speeding up further allocations.
+ Another way would be to call GC::Collect() at a convenient point in the code,
+ but this may be less optimal as it may still cause unnecessary allocations
+ of memory if native resources were not released early enough. In this program
+ we call GC::Collect() after every example (see Examples.cs) to make sure
+ everything is returned to the memory pool at latest before running the next
+ example.
+ */
+ using SEALContext context = new SEALContext(parms);
+
+ /*
+ Print the parameters that we have chosen.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Set encryption parameters and print");
+ Utilities.PrintParameters(context);
+
+ /*
+ When parameters are used to create SEALContext, Microsoft SEAL will first
+ validate those parameters. The parameters chosen here are valid.
+ */
+ Console.WriteLine("Parameter validation (success): {0}", context.ParameterErrorMessage());
+
+ Console.WriteLine();
+ Console.WriteLine("~~~~~~ A naive way to calculate 4(x^2+1)(x+1)^2. ~~~~~~");
+
+ /*
+ The encryption schemes in Microsoft SEAL are public key encryption schemes.
+ For users unfamiliar with this terminology, a public key encryption scheme
+ has a separate public key for encrypting data, and a separate secret key for
+ decrypting data. This way multiple parties can encrypt data using the same
+ shared public key, but only the proper recipient of the data can decrypt it
+ with the secret key.
+
+ We are now ready to generate the secret and public keys. For this purpose
+ we need an instance of the KeyGenerator class. Constructing a KeyGenerator
+ automatically generates the public and secret key, which can immediately be
+ read to local variables.
+ */
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+
+ /*
+ To be able to encrypt we need to construct an instance of Encryptor. Note
+ that the Encryptor only requires the public key, as expected.
+ */
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+
+ /*
+ Computations on the ciphertexts are performed with the Evaluator class. In
+ a real use-case the Evaluator would not be constructed by the same party
+ that holds the secret key.
+ */
+ using Evaluator evaluator = new Evaluator(context);
+
+ /*
+ We will of course want to decrypt our results to verify that everything worked,
+ so we need to also construct an instance of Decryptor. Note that the Decryptor
+ requires the secret key.
+ */
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ /*
+ As an example, we evaluate the degree 4 polynomial
+
+ 4x^4 + 8x^3 + 8x^2 + 8x + 4
+
+ over an encrypted x = 6. The coefficients of the polynomial can be considered
+ as plaintext inputs, as we will see below. The computation is done modulo the
+ plain_modulus 1024.
+
+ While this examples is simple and easy to understand, it does not have much
+ practical value. In later examples we will demonstrate how to compute more
+ efficiently on encrypted integers and real or complex numbers.
+
+ Plaintexts in the BFV scheme are polynomials of degree less than the degree
+ of the polynomial modulus, and coefficients integers modulo the plaintext
+ modulus. For readers with background in ring theory, the plaintext space is
+ the polynomial quotient ring Z_T[X]/(X^N + 1), where N is PolyModulusDegree
+ and T is PlainModulus.
+
+ To get started, we create a plaintext containing the constant 6. For the
+ plaintext element we use a constructor that takes the desired polynomial as
+ a string with coefficients represented as hexadecimal numbers.
+ */
+ Utilities.PrintLine();
+ int x = 6;
+ using Plaintext xPlain = new Plaintext(x.ToString());
+ Console.WriteLine($"Express x = {x} as a plaintext polynomial 0x{xPlain}.");
+
+ /*
+ We then encrypt the plaintext, producing a ciphertext.
+ */
+ Utilities.PrintLine();
+ using Ciphertext xEncrypted = new Ciphertext();
+ Console.WriteLine("Encrypt xPlain to xEncrypted.");
+ encryptor.Encrypt(xPlain, xEncrypted);
+
+ /*
+ In Microsoft SEAL, a valid ciphertext consists of two or more polynomials
+ whose coefficients are integers modulo the product of the primes in the
+ coeff_modulus. The number of polynomials in a ciphertext is called its `size'
+ and is given by Ciphertext.Size. A freshly encrypted ciphertext always has
+ size 2.
+ */
+ Console.WriteLine($" + size of freshly encrypted x: {xEncrypted.Size}");
+
+ /*
+ There is plenty of noise budget left in this freshly encrypted ciphertext.
+ */
+ Console.WriteLine(" + noise budget in freshly encrypted x: {0} bits",
+ decryptor.InvariantNoiseBudget(xEncrypted));
+
+ /*
+ We decrypt the ciphertext and print the resulting plaintext in order to
+ demonstrate correctness of the encryption.
+ */
+ using Plaintext xDecrypted = new Plaintext();
+ Console.Write(" + decryption of encrypted_x: ");
+ decryptor.Decrypt(xEncrypted, xDecrypted);
+ Console.WriteLine($"0x{xDecrypted} ...... Correct.");
+
+ /*
+ When using Microsoft SEAL, it is typically advantageous to compute in a way
+ that minimizes the longest chain of sequential multiplications. In other
+ words, encrypted computations are best evaluated in a way that minimizes
+ the multiplicative depth of the computation, because the total noise budget
+ consumption is proportional to the multiplicative depth. For example, for
+ our example computation it is advantageous to factorize the polynomial as
+
+ 4x^4 + 8x^3 + 8x^2 + 8x + 4 = 4(x + 1)^2 * (x^2 + 1)
+
+ to obtain a simple depth 2 representation. Thus, we compute (x + 1)^2 and
+ (x^2 + 1) separately, before multiplying them, and multiplying by 4.
+
+ First, we compute x^2 and add a plaintext "1". We can clearly see from the
+ print-out that multiplication has consumed a lot of noise budget. The user
+ can vary the plain_modulus parameter to see its effect on the rate of noise
+ budget consumption.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute xSqPlusOne (x^2+1).");
+ using Ciphertext xSqPlusOne = new Ciphertext();
+ evaluator.Square(xEncrypted, xSqPlusOne);
+ using Plaintext plainOne = new Plaintext("1");
+ evaluator.AddPlainInplace(xSqPlusOne, plainOne);
+
+ /*
+ Encrypted multiplication results in the output ciphertext growing in size.
+ More precisely, if the input ciphertexts have size M and N, then the output
+ ciphertext after homomorphic multiplication will have size M+N-1. In this
+ case we perform a squaring, and observe both size growth and noise budget
+ consumption.
+ */
+ Console.WriteLine($" + size of xSqPlusOne: {xSqPlusOne.Size}");
+ Console.WriteLine(" + noise budget in xSqPlusOne: {0} bits",
+ decryptor.InvariantNoiseBudget(xSqPlusOne));
+
+ /*
+ Even though the size has grown, decryption works as usual as long as noise
+ budget has not reached 0.
+ */
+ using Plaintext decryptedResult = new Plaintext();
+ Console.Write(" + decryption of xSqPlusOne: ");
+ decryptor.Decrypt(xSqPlusOne, decryptedResult);
+ Console.WriteLine($"0x{decryptedResult} ...... Correct.");
+
+ /*
+ Next, we compute (x + 1)^2.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute xPlusOneSq ((x+1)^2).");
+ using Ciphertext xPlusOneSq = new Ciphertext();
+ evaluator.AddPlain(xEncrypted, plainOne, xPlusOneSq);
+ evaluator.SquareInplace(xPlusOneSq);
+ Console.WriteLine($" + size of xPlusOneSq: {xPlusOneSq.Size}");
+ Console.WriteLine(" + noise budget in xPlusOneSq: {0} bits",
+ decryptor.InvariantNoiseBudget(xPlusOneSq));
+ Console.Write(" + decryption of xPlusOneSq: ");
+ decryptor.Decrypt(xPlusOneSq, decryptedResult);
+ Console.WriteLine($"0x{decryptedResult} ...... Correct.");
+
+ /*
+ Finally, we multiply (x^2 + 1) * (x + 1)^2 * 4.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute encryptedResult (4(x^2+1)(x+1)^2).");
+ using Ciphertext encryptedResult = new Ciphertext();
+ using Plaintext plainFour = new Plaintext("4");
+ evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour);
+ evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult);
+ Console.WriteLine($" + size of encrypted_result: {encryptedResult.Size}");
+ Console.WriteLine(" + noise budget in encrypted_result: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedResult));
+ Console.WriteLine("NOTE: Decryption can be incorrect if noise budget is zero.");
+
+ Console.WriteLine();
+ Console.WriteLine("~~~~~~ A better way to calculate 4(x^2+1)(x+1)^2. ~~~~~~");
+
+ /*
+ Noise budget has reached 0, which means that decryption cannot be expected
+ to give the correct result. This is because both ciphertexts xSqPlusOne and
+ xPlusOneSq 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.
+
+ `Relinearization' is an operation that reduces the size of a ciphertext after
+ multiplication back to the initial size, 2. Thus, relinearizing one or both
+ input ciphertexts before the next multiplication can have a huge positive
+ impact on both noise growth and performance, even though relinearization has
+ a significant computational cost itself. It is only possible to relinearize
+ size 3 ciphertexts down to size 2, so often the user would want to relinearize
+ after each multiplication to keep the ciphertext sizes at 2.
+
+ Relinearization requires special `relinearization keys', which can be thought
+ of as a kind of public key. Relinearization keys can easily be created with
+ the KeyGenerator.
+
+ Relinearization is used similarly in both the BFV and the CKKS schemes, but
+ in this example we continue using BFV. We repeat our computation from before,
+ but this time relinearize after every multiplication.
+
+ Here we use the function KeyGenerator.RelinKeysLocal(). In production code
+ it is much better to use KeyGenerator.RelinKeys() instead. We will explain
+ and discuss these differences in `6_Serialization.cs'.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Generate locally usable relinearization keys.");
+ using RelinKeys relinKeys = keygen.RelinKeysLocal();
+
+ /*
+ We now repeat the computation relinearizing after each multiplication.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute and relinearize xSquared (x^2),");
+ Console.WriteLine(new string(' ', 13) + "then compute xSqPlusOne (x^2+1)");
+ using Ciphertext xSquared = new Ciphertext();
+ evaluator.Square(xEncrypted, xSquared);
+ Console.WriteLine($" + size of xSquared: {xSquared.Size}");
+ evaluator.RelinearizeInplace(xSquared, relinKeys);
+ Console.WriteLine(" + size of xSquared (after relinearization): {0}",
+ xSquared.Size);
+ evaluator.AddPlain(xSquared, plainOne, xSqPlusOne);
+ Console.WriteLine(" + noise budget in xSqPlusOne: {0} bits",
+ decryptor.InvariantNoiseBudget(xSqPlusOne));
+ Console.Write(" + decryption of xSqPlusOne: ");
+ decryptor.Decrypt(xSqPlusOne, decryptedResult);
+ Console.WriteLine($"0x{decryptedResult} ...... Correct.");
+
+ Utilities.PrintLine();
+ using Ciphertext xPlusOne = new Ciphertext();
+ Console.WriteLine("Compute xPlusOne (x+1),");
+ Console.WriteLine(new string(' ', 13) +
+ "then compute and relinearize xPlusOneSq ((x+1)^2).");
+ evaluator.AddPlain(xEncrypted, plainOne, xPlusOne);
+ evaluator.Square(xPlusOne, xPlusOneSq);
+ Console.WriteLine($" + size of xPlusOneSq: {xPlusOneSq.Size}");
+ evaluator.RelinearizeInplace(xPlusOneSq, relinKeys);
+ Console.WriteLine(" + noise budget in xPlusOneSq: {0} bits",
+ decryptor.InvariantNoiseBudget(xPlusOneSq));
+ Console.Write(" + decryption of xPlusOneSq: ");
+ decryptor.Decrypt(xPlusOneSq, decryptedResult);
+ Console.WriteLine($"0x{decryptedResult} ...... Correct.");
+
+ Utilities.PrintLine();
+ Console.WriteLine("Compute and relinearize encryptedResult (4(x^2+1)(x+1)^2).");
+ evaluator.MultiplyPlainInplace(xSqPlusOne, plainFour);
+ evaluator.Multiply(xSqPlusOne, xPlusOneSq, encryptedResult);
+ Console.WriteLine($" + size of encryptedResult: {encryptedResult.Size}");
+ evaluator.RelinearizeInplace(encryptedResult, relinKeys);
+ Console.WriteLine(" + size of encryptedResult (after relinearization): {0}",
+ encryptedResult.Size);
+ Console.WriteLine(" + noise budget in encryptedResult: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedResult));
+
+ Console.WriteLine();
+ Console.WriteLine("NOTE: Notice the increase in remaining noise budget.");
+
+ /*
+ Relinearization clearly improved our noise consumption. We have still plenty
+ of noise budget left, so we can expect the correct answer when decrypting.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Decrypt encrypted_result (4(x^2+1)(x+1)^2).");
+ decryptor.Decrypt(encryptedResult, decryptedResult);
+ Console.WriteLine(" + decryption of 4(x^2+1)(x+1)^2 = 0x{0} ...... Correct.",
+ decryptedResult);
+
+ /*
+ For x=6, 4(x^2+1)(x+1)^2 = 7252. Since the plaintext modulus is set to 1024,
+ this result is computed in integers modulo 1024. Therefore the expected output
+ should be 7252 % 1024 == 84, or 0x54 in hexadecimal.
+ */
+
+ /*
+ Sometimes we create customized encryption parameters which turn out to be invalid.
+ Microsoft SEAL can interpret the reason why parameters are considered invalid.
+ Here we simply reduce the polynomial modulus degree to make the parameters not
+ compliant with the HomomorphicEncryption.org security standard.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("An example of invalid parameters");
+ parms.PolyModulusDegree = 2048;
+ using SEALContext new_context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+ Console.WriteLine("Parameter validation (failed): {0}", new_context.ParameterErrorMessage());
+
+ /*
+ This information is helpful to fix invalid encryption parameters.
+ */
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/2_Encoders.cs b/bigpiseal3.5.1/dotnet/examples/2_Encoders.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d74c0146959e0792ad2b8ed6232adac5281aeaa9
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/2_Encoders.cs
@@ -0,0 +1,487 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using Microsoft.Research.SEAL;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ /*
+ In `1_BFV_Basics.cs' we showed how to perform a very simple computation using the
+ BFV scheme. The computation was performed modulo the PlainModulus parameter, and
+ utilized only one coefficient from a BFV plaintext polynomial. This approach has
+ two notable problems:
+
+ (1) Practical applications typically use integer or real number arithmetic,
+ not modular arithmetic;
+ (2) We used only one coefficient of the plaintext polynomial. This is really
+ wasteful, as the plaintext polynomial is large and will in any case be
+ encrypted in its entirety.
+
+ For (1), one may ask why not just increase the PlainModulus parameter until no
+ overflow occurs, and the computations behave as in integer arithmetic. The problem
+ is that increasing PlainModulus increases noise budget consumption, and decreases
+ the initial noise budget too.
+
+ In these examples we will discuss other ways of laying out data into plaintext
+ elements (encoding) that allow more computations without data type overflow, and
+ can allow the full plaintext polynomial to be utilized.
+ */
+ private static void ExampleIntegerEncoder()
+ {
+ Utilities.PrintExampleBanner("Example: Encoders / Integer Encoder");
+
+ /*
+ [IntegerEncoder] (For BFV scheme only)
+
+ The IntegerEncoder encodes integers to BFV plaintext polynomials as follows.
+ First, a binary expansion of the integer is computed. Next, a polynomial is
+ created with the bits as coefficients. For example, the integer
+
+ 26 = 2^4 + 2^3 + 2^1
+
+ is encoded as the polynomial 1x^4 + 1x^3 + 1x^1. Conversely, plaintext
+ polynomials are decoded by evaluating them at x=2. For negative numbers the
+ IntegerEncoder simply stores all coefficients as either 0 or -1, where -1 is
+ represented by the unsigned integer PlainModulus - 1 in memory.
+
+ Since encrypted computations operate on the polynomials rather than on the
+ encoded integers themselves, the polynomial coefficients will grow in the
+ course of such computations. For example, computing the sum of the encrypted
+ encoded integer 26 with itself will result in an encrypted polynomial with
+ larger coefficients: 2x^4 + 2x^3 + 2x^1. Squaring the encrypted encoded
+ integer 26 results also in increased coefficients due to cross-terms, namely,
+
+ (1x^4 + 1x^3 + 1x^1)^2 = 1x^8 + 2x^7 + 1x^6 + 2x^5 + 2x^4 + 1x^2;
+
+ further computations will quickly increase the coefficients much more.
+ Decoding will still work correctly in this case (evaluating the polynomial
+ at x=2), but since the coefficients of plaintext polynomials are really
+ integers modulo plain_modulus, implicit reduction modulo plain_modulus may
+ yield unexpected results. For example, adding 1x^4 + 1x^3 + 1x^1 to itself
+ plain_modulus many times will result in the constant polynomial 0, which is
+ clearly not equal to 26 * plain_modulus. It can be difficult to predict when
+ such overflow will take place especially when computing several sequential
+ multiplications.
+
+ The IntegerEncoder is easy to understand and use for simple computations,
+ and can be a good tool to experiment with for users new to Microsoft SEAL.
+ However, advanced users will probably prefer more efficient approaches,
+ such as the BatchEncoder or the CKKSEncoder.
+ */
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+ ulong polyModulusDegree = 4096;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+
+ /*
+ There is no hidden logic behind our choice of the plain_modulus. The only
+ thing that matters is that the plaintext polynomial coefficients will not
+ exceed this value at any point during our computation; otherwise the result
+ will be incorrect.
+ */
+ parms.PlainModulus = new Modulus(512);
+ using SEALContext context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ /*
+ We create an IntegerEncoder.
+ */
+ using IntegerEncoder encoder = new IntegerEncoder(context);
+
+ /*
+ First, we encode two integers as plaintext polynomials. Note that encoding
+ is not encryption: at this point nothing is encrypted.
+ */
+ int value1 = 5;
+ using Plaintext plain1 = encoder.Encode(value1);
+ Utilities.PrintLine();
+ Console.WriteLine($"Encode {value1} as polynomial {plain1} (plain1),");
+
+ int value2 = -7;
+ using Plaintext plain2 = encoder.Encode(value2);
+ Console.WriteLine(new string(' ', 13)
+ + $"Encode {value2} as polynomial {plain2} (plain2),");
+
+ /*
+ Now we can encrypt the plaintext polynomials.
+ */
+ using Ciphertext encrypted1 = new Ciphertext();
+ using Ciphertext encrypted2 = new Ciphertext();
+ Utilities.PrintLine();
+ Console.WriteLine("Encrypt plain1 to encrypted1 and plain2 to encrypted2.");
+ encryptor.Encrypt(plain1, encrypted1);
+ encryptor.Encrypt(plain2, encrypted2);
+ Console.WriteLine(" + Noise budget in encrypted1: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted1));
+ Console.WriteLine(" + Noise budget in encrypted2: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted2));
+
+ /*
+ As a simple example, we compute (-encrypted1 + encrypted2) * encrypted2.
+ */
+ encryptor.Encrypt(plain2, encrypted2);
+ using Ciphertext encryptedResult = new Ciphertext();
+ Utilities.PrintLine();
+ Console.WriteLine("Compute encrypted_result = (-encrypted1 + encrypted2) * encrypted2.");
+ evaluator.Negate(encrypted1, encryptedResult);
+ evaluator.AddInplace(encryptedResult, encrypted2);
+ evaluator.MultiplyInplace(encryptedResult, encrypted2);
+ Console.WriteLine(" + Noise budget in encryptedResult: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedResult));
+
+ using Plaintext plainResult = new Plaintext();
+ Utilities.PrintLine();
+ Console.WriteLine("Decrypt encrypted_result to plain_result.");
+ decryptor.Decrypt(encryptedResult, plainResult);
+
+ /*
+ Print the result plaintext polynomial. The coefficients are not even close
+ to exceeding our plainModulus, 512.
+ */
+ Console.WriteLine($" + Plaintext polynomial: {plainResult}");
+
+ /*
+ Decode to obtain an integer result.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Decode plain_result.");
+ Console.WriteLine(" + Decoded integer: {0} ...... Correct.",
+ encoder.DecodeInt32(plainResult));
+ }
+
+ private static void ExampleBatchEncoder()
+ {
+ Utilities.PrintExampleBanner("Example: Encoders / Batch Encoder");
+
+ /*
+ [BatchEncoder] (For BFV scheme only)
+
+ Let N denote the PolyModulusDegree and T denote the PlainModulus. Batching
+ allows the BFV plaintext polynomials to be viewed as 2-by-(N/2) matrices, with
+ each element an integer modulo T. In the matrix view, encrypted operations act
+ element-wise on encrypted matrices, allowing the user to obtain speeds-ups of
+ several orders of magnitude in fully vectorizable computations. Thus, in all
+ but the simplest computations, batching should be the preferred method to use
+ with BFV, and when used properly will result in implementations outperforming
+ anything done with the IntegerEncoder.
+ */
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+ ulong polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+
+ /*
+ To enable batching, we need to set the plain_modulus to be a prime number
+ congruent to 1 modulo 2*PolyModulusDegree. Microsoft SEAL provides a helper
+ method for finding such a prime. In this example we create a 20-bit prime
+ that supports batching.
+ */
+ parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20);
+
+ using SEALContext context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ /*
+ We can verify that batching is indeed enabled by looking at the encryption
+ parameter qualifiers created by SEALContext.
+ */
+ using var qualifiers = context.FirstContextData.Qualifiers;
+ Console.WriteLine($"Batching enabled: {qualifiers.UsingBatching}");
+
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+ using RelinKeys relinKeys = keygen.RelinKeysLocal();
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ /*
+ Batching is done through an instance of the BatchEncoder class.
+ */
+ using BatchEncoder batchEncoder = new BatchEncoder(context);
+
+ /*
+ The total number of batching `slots' equals the PolyModulusDegree, N, and
+ these slots are organized into 2-by-(N/2) matrices that can be encrypted and
+ computed on. Each slot contains an integer modulo PlainModulus.
+ */
+ ulong slotCount = batchEncoder.SlotCount;
+ ulong rowSize = slotCount / 2;
+ Console.WriteLine($"Plaintext matrix row size: {rowSize}");
+
+ /*
+ The matrix plaintext is simply given to BatchEncoder as a flattened vector
+ of numbers. The first `rowSize' many numbers form the first row, and the
+ rest form the second row. Here we create the following matrix:
+
+ [ 0, 1, 2, 3, 0, 0, ..., 0 ]
+ [ 4, 5, 6, 7, 0, 0, ..., 0 ]
+ */
+ ulong[] podMatrix = new ulong[slotCount];
+ podMatrix[0] = 0;
+ podMatrix[1] = 1;
+ podMatrix[2] = 2;
+ podMatrix[3] = 3;
+ podMatrix[rowSize] = 4;
+ podMatrix[rowSize + 1] = 5;
+ podMatrix[rowSize + 2] = 6;
+ podMatrix[rowSize + 3] = 7;
+
+ Console.WriteLine("Input plaintext matrix:");
+ Utilities.PrintMatrix(podMatrix, (int)rowSize);
+
+ /*
+ First we use BatchEncoder to encode the matrix into a plaintext polynomial.
+ */
+ using Plaintext plainMatrix = new Plaintext();
+ Utilities.PrintLine();
+ Console.WriteLine("Encode plaintext matrix:");
+ batchEncoder.Encode(podMatrix, plainMatrix);
+
+ /*
+ We can instantly decode to verify correctness of the encoding. Note that no
+ encryption or decryption has yet taken place.
+ */
+ List podResult = new List();
+ Console.WriteLine(" + Decode plaintext matrix ...... Correct.");
+ batchEncoder.Decode(plainMatrix, podResult);
+ Utilities.PrintMatrix(podResult, (int)rowSize);
+
+ /*
+ Next we encrypt the encoded plaintext.
+ */
+ using Ciphertext encryptedMatrix = new Ciphertext();
+ Utilities.PrintLine();
+ Console.WriteLine("Encrypt plainMatrix to encryptedMatrix.");
+ encryptor.Encrypt(plainMatrix, encryptedMatrix);
+ Console.WriteLine(" + Noise budget in encryptedMatrix: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedMatrix));
+
+ /*
+ Operating on the ciphertext results in homomorphic operations being performed
+ simultaneously in all 8192 slots (matrix elements). To illustrate this, we
+ form another plaintext matrix
+
+ [ 1, 2, 1, 2, 1, 2, ..., 2 ]
+ [ 1, 2, 1, 2, 1, 2, ..., 2 ]
+
+ and encode it into a plaintext.
+ */
+ ulong[] podMatrix2 = new ulong[slotCount];
+ for (ulong i = 0; i < slotCount; i++)
+ {
+ podMatrix2[i] = (i % 2) + 1;
+ }
+ using Plaintext plainMatrix2 = new Plaintext();
+ batchEncoder.Encode(podMatrix2, plainMatrix2);
+ Console.WriteLine();
+ Console.WriteLine("Second input plaintext matrix:");
+ Utilities.PrintMatrix(podMatrix2, (int)rowSize);
+
+ /*
+ We now add the second (plaintext) matrix to the encrypted matrix, and square
+ the sum.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Sum, square, and relinearize.");
+ evaluator.AddPlainInplace(encryptedMatrix, plainMatrix2);
+ evaluator.SquareInplace(encryptedMatrix);
+ evaluator.RelinearizeInplace(encryptedMatrix, relinKeys);
+
+ /*
+ How much noise budget do we have left?
+ */
+ Console.WriteLine(" + Noise budget in result: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedMatrix));
+
+ /*
+ We decrypt and decompose the plaintext to recover the result as a matrix.
+ */
+ using Plaintext plainResult = new Plaintext();
+ Utilities.PrintLine();
+ Console.WriteLine("Decrypt and decode result.");
+ decryptor.Decrypt(encryptedMatrix, plainResult);
+ batchEncoder.Decode(plainResult, podResult);
+ Console.WriteLine(" + Result plaintext matrix ...... Correct.");
+ Utilities.PrintMatrix(podResult, (int)rowSize);
+
+ /*
+ Batching allows us to efficiently use the full plaintext polynomial when the
+ desired encrypted computation is highly parallelizable. However, it has not
+ solved the other problem mentioned in the beginning of this file: each slot
+ holds only an integer modulo plain_modulus, and unless plain_modulus is very
+ large, we can quickly encounter data type overflow and get unexpected results
+ when integer computations are desired. Note that overflow cannot be detected
+ in encrypted form. The CKKS scheme (and the CKKSEncoder) addresses the data
+ type overflow issue, but at the cost of yielding only approximate results.
+ */
+ }
+
+ static private void ExampleCKKSEncoder()
+ {
+ Utilities.PrintExampleBanner("Example: Encoders / CKKS Encoder");
+
+ /*
+ [CKKSEncoder] (For CKKS scheme only)
+
+ In this example we demonstrate the Cheon-Kim-Kim-Song (CKKS) scheme for
+ computing on encrypted real or complex numbers. We start by creating
+ encryption parameters for the CKKS scheme. There are two important
+ differences compared to the BFV scheme:
+
+ (1) CKKS does not use the PlainModulus encryption parameter;
+ (2) Selecting the CoeffModulus in a specific way can be very important
+ when using the CKKS scheme. We will explain this further in the file
+ `CKKS_Basics.cs'. In this example we use CoeffModulus.Create to
+ generate 5 40-bit prime numbers.
+ */
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+
+ ulong polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.Create(
+ polyModulusDegree, new int[]{ 40, 40, 40, 40, 40 });
+
+ /*
+ We create the SEALContext as usual and print the parameters.
+ */
+ using SEALContext context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ /*
+ Keys are created the same way as for the BFV scheme.
+ */
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+ using RelinKeys relinKeys = keygen.RelinKeysLocal();
+
+ /*
+ We also set up an Encryptor, Evaluator, and Decryptor as usual.
+ */
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ /*
+ To create CKKS plaintexts we need a special encoder: there is no other way
+ to create them. The IntegerEncoder and BatchEncoder cannot be used with the
+ CKKS scheme. The CKKSEncoder encodes vectors of real or complex numbers into
+ Plaintext objects, which can subsequently be encrypted. At a high level this
+ looks a lot like what BatchEncoder does for the BFV scheme, but the theory
+ behind it is completely different.
+ */
+ using CKKSEncoder encoder = new CKKSEncoder(context);
+
+ /*
+ In CKKS the number of slots is PolyModulusDegree / 2 and each slot encodes
+ one real or complex number. This should be contrasted with BatchEncoder in
+ the BFV scheme, where the number of slots is equal to PolyModulusDegree
+ and they are arranged into a matrix with two rows.
+ */
+ ulong slotCount = encoder.SlotCount;
+ Console.WriteLine($"Number of slots: {slotCount}");
+
+ /*
+ We create a small vector to encode; the CKKSEncoder will implicitly pad it
+ with zeros to full size (PolyModulusDegree / 2) when encoding.
+ */
+ double[] input = new double[]{ 0.0, 1.1, 2.2, 3.3 };
+ Console.WriteLine("Input vector: ");
+ Utilities.PrintVector(input);
+
+ /*
+ Now we encode it with CKKSEncoder. The floating-point coefficients of `input'
+ will be scaled up by the parameter `scale'. This is necessary since even in
+ the CKKS scheme the plaintext elements are fundamentally polynomials with
+ integer coefficients. It is instructive to think of the scale as determining
+ the bit-precision of the encoding; naturally it will affect the precision of
+ the result.
+
+ In CKKS the message is stored modulo CoeffModulus (in BFV it is stored modulo
+ PlainModulus), so the scaled message must not get too close to the total size
+ of CoeffModulus. In this case our CoeffModulus is quite large (200 bits) so
+ we have little to worry about in this regard. For this simple example a 30-bit
+ scale is more than enough.
+ */
+ using Plaintext plain = new Plaintext();
+ double scale = Math.Pow(2.0, 30);
+ Utilities.PrintLine();
+ Console.WriteLine("Encode input vector.");
+ encoder.Encode(input, scale, plain);
+
+ /*
+ We can instantly decode to check the correctness of encoding.
+ */
+ List output = new List();
+ Console.WriteLine(" + Decode input vector ...... Correct.");
+ encoder.Decode(plain, output);
+ Utilities.PrintVector(output);
+
+ /*
+ The vector is encrypted the same was as in BFV.
+ */
+ using Ciphertext encrypted = new Ciphertext();
+ Utilities.PrintLine();
+ Console.WriteLine("Encrypt input vector, square, and relinearize.");
+ encryptor.Encrypt(plain, encrypted);
+
+ /*
+ Basic operations on the ciphertexts are still easy to do. Here we square
+ the ciphertext, decrypt, decode, and print the result. We note also that
+ decoding returns a vector of full size (PolyModulusDegree / 2); this is
+ because of the implicit zero-padding mentioned above.
+ */
+ evaluator.SquareInplace(encrypted);
+ evaluator.RelinearizeInplace(encrypted, relinKeys);
+
+ /*
+ We notice that the scale in the result has increased. In fact, it is now
+ the square of the original scale: 2^60.
+ */
+ Console.WriteLine(" + Scale in squared input: {0} ({1} bits)",
+ encrypted.Scale,
+ (int)Math.Ceiling(Math.Log(encrypted.Scale, newBase: 2)));
+ Utilities.PrintLine();
+ Console.WriteLine("Decrypt and decode.");
+ decryptor.Decrypt(encrypted, plain);
+ encoder.Decode(plain, output);
+ Console.WriteLine(" + Result vector ...... Correct.");
+ Utilities.PrintVector(output);
+
+ /*
+ The CKKS scheme allows the scale to be reduced between encrypted computations.
+ This is a fundamental and critical feature that makes CKKS very powerful and
+ flexible. We will discuss it in great detail in `3_Levels.cs' and later in
+ `4_CKKS_Basics.cs'.
+ */
+ }
+
+ private static void ExampleEncoders()
+ {
+ Utilities.PrintExampleBanner("Example: Encoders");
+
+ /*
+ Run all encoder examples.
+ */
+ ExampleIntegerEncoder();
+ ExampleBatchEncoder();
+ ExampleCKKSEncoder();
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/3_Levels.cs b/bigpiseal3.5.1/dotnet/examples/3_Levels.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bc0b27bfb5369b0515f633a16b8c87425b857736
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/3_Levels.cs
@@ -0,0 +1,348 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using Microsoft.Research.SEAL;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ private static void ExampleLevels()
+ {
+ Utilities.PrintExampleBanner("Example: Levels");
+
+ /*
+ In this examples we describe the concept of `levels' in BFV and CKKS and the
+ related objects that represent them in Microsoft SEAL.
+
+ In Microsoft SEAL a set of encryption parameters (excluding the random number
+ generator) is identified uniquely by a 256-bit hash of the parameters. This
+ hash is called the `ParmsId' and can be easily accessed and printed at any
+ time. The hash will change as soon as any of the parameters is changed.
+
+ When a SEALContext is created from a given EncryptionParameters instance,
+ Microsoft SEAL automatically creates a so-called `modulus switching chain',
+ which is a chain of other encryption parameters derived from the original set.
+ The parameters in the modulus switching chain are the same as the original
+ parameters with the exception that size of the coefficient modulus is
+ decreasing going down the chain. More precisely, each parameter set in the
+ chain attempts to remove the last coefficient modulus prime from the
+ previous set; this continues until the parameter set is no longer valid
+ (e.g., PlainModulus is larger than the remaining CoeffModulus). It is easy
+ to walk through the chain and access all the parameter sets. Additionally,
+ each parameter set in the chain has a `chain index' that indicates its
+ position in the chain so that the last set has index 0. We say that a set
+ of encryption parameters, or an object carrying those encryption parameters,
+ is at a higher level in the chain than another set of parameters if its the
+ chain index is bigger, i.e., it is earlier in the chain.
+
+ Each set of parameters in the chain involves unique pre-computations performed
+ when the SEALContext is created, and stored in a SEALContext.ContextData
+ object. The chain is basically a linked list of SEALContext.ContextData
+ objects, and can easily be accessed through the SEALContext at any time. Each
+ node can be identified by the ParmsId of its specific encryption parameters
+ (PolyModulusDegree remains the same but CoeffModulus varies).
+ */
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+ ulong polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+
+ /*
+ In this example we use a custom CoeffModulus, consisting of 5 primes of
+ sizes 50, 30, 30, 50, and 50 bits. Note that this is still OK according to
+ the explanation in `1_BFV_Basics.cs'. Indeed,
+
+ CoeffModulus.MaxBitCount(polyModulusDegree)
+
+ returns 218 (greater than 50+30+30+50+50=210).
+
+ Due to the modulus switching chain, the order of the 5 primes is significant.
+ The last prime has a special meaning and we call it the `special prime'. Thus,
+ the first parameter set in the modulus switching chain is the only one that
+ involves the special prime. All key objects, such as SecretKey, are created
+ at this highest level. All data objects, such as Ciphertext, can be only at
+ lower levels. The special modulus should be as large as the largest of the
+ other primes in the CoeffModulus, although this is not a strict requirement.
+
+ special prime +---------+
+ |
+ v
+ CoeffModulus: { 50, 30, 30, 50, 50 } +---+ Level 4 (all keys; `key level')
+ |
+ |
+ CoeffModulus: { 50, 30, 30, 50 } +---+ Level 3 (highest `data level')
+ |
+ |
+ CoeffModulus: { 50, 30, 30 } +---+ Level 2
+ |
+ |
+ CoeffModulus: { 50, 30 } +---+ Level 1
+ |
+ |
+ CoeffModulus: { 50 } +---+ Level 0 (lowest level)
+ */
+ parms.CoeffModulus = CoeffModulus.Create(
+ polyModulusDegree, new int[] { 50, 30, 30, 50, 50 });
+
+ /*
+ In this example the PlainModulus does not play much of a role; we choose
+ some reasonable value.
+ */
+ parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20);
+
+ using SEALContext context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+
+ /*
+ There are convenience method for accessing the SEALContext.ContextData for
+ some of the most important levels:
+
+ SEALContext.KeyContextData: access to key level ContextData
+ SEALContext.FirstContextData: access to highest data level ContextData
+ SEALContext.LastContextData: access to lowest level ContextData
+
+ We iterate over the chain and print the ParmsId for each set of parameters.
+ */
+ Console.WriteLine();
+ Utilities.PrintLine();
+ Console.WriteLine("Print the modulus switching chain.");
+
+ /*
+ First print the key level parameter information.
+ */
+ SEALContext.ContextData contextData = context.KeyContextData;
+ Console.WriteLine("----> Level (chain index): {0} ...... KeyContextData",
+ contextData.ChainIndex);
+ Console.WriteLine($" ParmsId: {contextData.ParmsId}");
+ Console.Write(" CoeffModulus primes: ");
+ foreach (Modulus prime in contextData.Parms.CoeffModulus)
+ {
+ Console.Write($"{Utilities.ULongToString(prime.Value)} ");
+ }
+ Console.WriteLine();
+ Console.WriteLine("\\");
+ Console.Write(" \\--> ");
+
+ /*
+ Next iterate over the remaining (data) levels.
+ */
+ contextData = context.FirstContextData;
+ while (null != contextData)
+ {
+ Console.Write($"Level (chain index): {contextData.ChainIndex}");
+ if (contextData.ParmsId.Equals(context.FirstParmsId))
+ {
+ Console.WriteLine(" ...... FirstContextData");
+ }
+ else if (contextData.ParmsId.Equals(context.LastParmsId))
+ {
+ Console.WriteLine(" ...... LastContextData");
+ }
+ else
+ {
+ Console.WriteLine();
+ }
+ Console.WriteLine($" ParmsId: {contextData.ParmsId}");
+ Console.Write(" CoeffModulus primes: ");
+ foreach (Modulus prime in contextData.Parms.CoeffModulus)
+ {
+ Console.Write($"{Utilities.ULongToString(prime.Value)} ");
+ }
+ Console.WriteLine();
+ Console.WriteLine("\\");
+ Console.Write(" \\--> ");
+
+ /*
+ Step forward in the chain.
+ */
+ contextData = contextData.NextContextData;
+ }
+ Console.WriteLine("End of chain reached");
+ Console.WriteLine();
+
+ /*
+ We create some keys and check that indeed they appear at the highest level.
+ */
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+ using RelinKeys relinKeys = keygen.RelinKeysLocal();
+
+ /*
+ In this example we create a local version of the GaloisKeys object using
+ KeyGenerator.GaloisKeysLocal(). In a production setting where the Galois
+ keys would need to be communicated to a server, it would be much better to
+ use KeyGenerator.GaloisKeys(), which outputs a Serializable
+ object for compressed serialization.
+ */
+ using GaloisKeys galoisKeys = keygen.GaloisKeysLocal();
+ Utilities.PrintLine();
+ Console.WriteLine("Print the parameter IDs of generated elements.");
+ Console.WriteLine($" + publicKey: {publicKey.ParmsId}");
+ Console.WriteLine($" + secretKey: {secretKey.ParmsId}");
+ Console.WriteLine($" + relinKeys: {relinKeys.ParmsId}");
+ Console.WriteLine($" + galoisKeys: {galoisKeys.ParmsId}");
+
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ /*
+ In the BFV scheme plaintexts do not carry a ParmsId, but ciphertexts do. Note
+ how the freshly encrypted ciphertext is at the highest data level.
+ */
+ using Plaintext plain = new Plaintext("1x^3 + 2x^2 + 3x^1 + 4");
+ using Ciphertext encrypted = new Ciphertext();
+ encryptor.Encrypt(plain, encrypted);
+ Console.WriteLine($" + plain: {plain.ParmsId} (not set in BFV)");
+ Console.WriteLine($" + encrypted: {encrypted.ParmsId}");
+ Console.WriteLine();
+
+ /*
+ `Modulus switching' is a technique of changing the ciphertext parameters down
+ in the chain. The function Evaluator.ModSwitchToNext always switches to the
+ next level down the chain, whereas Evaluator.ModSwitchTo switches to a parameter
+ set down the chain corresponding to a given ParmsId. However, it is impossible
+ to switch up in the chain.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Perform modulus switching on encrypted and print.");
+ contextData = context.FirstContextData;
+ Console.Write("----> ");
+ while (null != contextData.NextContextData)
+ {
+ Console.WriteLine($"Level (chain index): {contextData.ChainIndex}");
+ Console.WriteLine($" ParmsId of encrypted: {contextData.ParmsId}");
+ Console.WriteLine(" Noise budget at this level: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+ Console.WriteLine("\\");
+ Console.Write(" \\--> ");
+ evaluator.ModSwitchToNextInplace(encrypted);
+ contextData = contextData.NextContextData;
+ }
+ Console.WriteLine($"Level (chain index): {contextData.ChainIndex}");
+ Console.WriteLine($" ParmsId of encrypted: {contextData.ParmsId}");
+ Console.WriteLine(" Noise budget at this level: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+ Console.WriteLine("\\");
+ Console.Write(" \\--> ");
+ Console.WriteLine("End of chain reached");
+ Console.WriteLine();
+
+ /*
+ At this point it is hard to see any benefit in doing this: we lost a huge
+ amount of noise budget (i.e., computational power) at each switch and seemed
+ to get nothing in return. Decryption still works.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Decrypt still works after modulus switching.");
+ decryptor.Decrypt(encrypted, plain);
+ Console.WriteLine($" + Decryption of encrypted: {plain} ...... Correct.");
+ Console.WriteLine();
+
+ /*
+ However, there is a hidden benefit: the size of the ciphertext depends
+ linearly on the number of primes in the coefficient modulus. Thus, if there
+ is no need or intention to perform any further computations on a given
+ ciphertext, we might as well switch it down to the smallest (last) set of
+ parameters in the chain before sending it back to the secret key holder for
+ decryption.
+
+ Also the lost noise budget is actually not an issue at all, if we do things
+ right, as we will see below.
+
+ First we recreate the original ciphertext and perform some computations.
+ */
+ Console.WriteLine("Computation is more efficient with modulus switching.");
+ Utilities.PrintLine();
+ Console.WriteLine("Compute the eight power.");
+ encryptor.Encrypt(plain, encrypted);
+ Console.WriteLine(" + Noise budget fresh: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+ evaluator.SquareInplace(encrypted);
+ evaluator.RelinearizeInplace(encrypted, relinKeys);
+ Console.WriteLine(" + Noise budget of the 2nd power: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+ evaluator.SquareInplace(encrypted);
+ evaluator.RelinearizeInplace(encrypted, relinKeys);
+ Console.WriteLine(" + Noise budget of the 4th power: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+ /*
+ Surprisingly, in this case modulus switching has no effect at all on the
+ noise budget.
+ */
+ evaluator.ModSwitchToNextInplace(encrypted);
+ Console.WriteLine(" + Noise budget after modulus switching: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+
+
+ /*
+ This means that there is no harm at all in dropping some of the coefficient
+ modulus after doing enough computations. In some cases one might want to
+ switch to a lower level slightly earlier, actually sacrificing some of the
+ noise budget in the process, to gain computational performance from having
+ smaller parameters. We see from the print-out that the next modulus switch
+ should be done ideally when the noise budget is down to around 25 bits.
+ */
+ evaluator.SquareInplace(encrypted);
+ evaluator.RelinearizeInplace(encrypted, relinKeys);
+ Console.WriteLine(" + Noise budget of the 8th power: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+ evaluator.ModSwitchToNextInplace(encrypted);
+ Console.WriteLine(" + Noise budget after modulus switching: {0} bits",
+ decryptor.InvariantNoiseBudget(encrypted));
+
+ /*
+ At this point the ciphertext still decrypts correctly, has very small size,
+ and the computation was as efficient as possible. Note that the decryptor
+ can be used to decrypt a ciphertext at any level in the modulus switching
+ chain.
+ */
+ decryptor.Decrypt(encrypted, plain);
+ Console.WriteLine(" + Decryption of the 8th power (hexadecimal) ...... Correct.");
+ Console.WriteLine($" {plain}");
+ Console.WriteLine();
+
+ /*
+ In BFV modulus switching is not necessary and in some cases the user might
+ not want to create the modulus switching chain, except for the highest two
+ levels. This can be done by passing a bool `false' to SEALContext constructor.
+ */
+ using SEALContext context2 = new SEALContext(parms, expandModChain: false);
+
+ /*
+ We can check that indeed the modulus switching chain has been created only
+ for the highest two levels (key level and highest data level). The following
+ loop should execute only once.
+ */
+ Console.WriteLine("Optionally disable modulus switching chain expansion.");
+ Utilities.PrintLine();
+ Console.WriteLine("Print the modulus switching chain.");
+ Console.Write("----> ");
+ for (contextData = context2.KeyContextData; null != contextData;
+ contextData = contextData.NextContextData)
+ {
+ Console.WriteLine($"Level (chain index): {contextData.ChainIndex}");
+ Console.WriteLine($" ParmsId of encrypted: {contextData.ParmsId}");
+ Console.Write(" CoeffModulus primes: ");
+ foreach (Modulus prime in contextData.Parms.CoeffModulus)
+ {
+ Console.Write($"{Utilities.ULongToString(prime.Value)} ");
+ }
+ Console.WriteLine();
+ Console.WriteLine("\\");
+ Console.Write(" \\--> ");
+ }
+ Console.WriteLine("End of chain reached");
+ Console.WriteLine();
+
+ /*
+ It is very important to understand how this example works since in the CKKS
+ scheme modulus switching has a much more fundamental purpose and the next
+ examples will be difficult to understand unless these basic properties are
+ totally clear.
+ */
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/4_CKKS_Basics.cs b/bigpiseal3.5.1/dotnet/examples/4_CKKS_Basics.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9a4f1cd60a8133813debe85414c14abc5d043aaa
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/4_CKKS_Basics.cs
@@ -0,0 +1,321 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using Microsoft.Research.SEAL;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ private static void ExampleCKKSBasics()
+ {
+ Utilities.PrintExampleBanner("Example: CKKS Basics");
+
+ /*
+ In this example we demonstrate evaluating a polynomial function
+
+ PI*x^3 + 0.4*x + 1
+
+ on encrypted floating-point input data x for a set of 4096 equidistant points
+ in the interval [0, 1]. This example demonstrates many of the main features
+ of the CKKS scheme, but also the challenges in using it.
+
+ We start by setting up the CKKS scheme.
+ */
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+
+ /*
+ We saw in `2_Encoders.cs' that multiplication in CKKS causes scales in
+ ciphertexts to grow. The scale of any ciphertext must not get too close to
+ the total size of CoeffModulus, or else the ciphertext simply runs out of
+ room to store the scaled-up plaintext. The CKKS scheme provides a `rescale'
+ functionality that can reduce the scale, and stabilize the scale expansion.
+
+ Rescaling is a kind of modulus switch operation (recall `3_Levels.cs').
+ As modulus switching, it removes the last of the primes from CoeffModulus,
+ but as a side-effect it scales down the ciphertext by the removed prime.
+ Usually we want to have perfect control over how the scales are changed,
+ which is why for the CKKS scheme it is more common to use carefully selected
+ primes for the CoeffModulus.
+
+ More precisely, suppose that the scale in a CKKS ciphertext is S, and the
+ last prime in the current CoeffModulus (for the ciphertext) is P. Rescaling
+ to the next level changes the scale to S/P, and removes the prime P from the
+ CoeffModulus, as usual in modulus switching. The number of primes limits
+ how many rescalings can be done, and thus limits the multiplicative depth of
+ the computation.
+
+ It is possible to choose the initial scale freely. One good strategy can be
+ to is to set the initial scale S and primes P_i in the CoeffModulus to be
+ very close to each other. If ciphertexts have scale S before multiplication,
+ they have scale S^2 after multiplication, and S^2/P_i after rescaling. If all
+ P_i are close to S, then S^2/P_i is close to S again. This way we stabilize the
+ scales to be close to S throughout the computation. Generally, for a circuit
+ of depth D, we need to rescale D times, i.e., we need to be able to remove D
+ primes from the coefficient modulus. Once we have only one prime left in the
+ coeff_modulus, the remaining prime must be larger than S by a few bits to
+ preserve the pre-decimal-point value of the plaintext.
+
+ Therefore, a generally good strategy is to choose parameters for the CKKS
+ scheme as follows:
+
+ (1) Choose a 60-bit prime as the first prime in CoeffModulus. This will
+ give the highest precision when decrypting;
+ (2) Choose another 60-bit prime as the last element of CoeffModulus, as
+ this will be used as the special prime and should be as large as the
+ largest of the other primes;
+ (3) Choose the intermediate primes to be close to each other.
+
+ We use CoeffModulus.Create to generate primes of the appropriate size. Note
+ that our CoeffModulus is 200 bits total, which is below the bound for our
+ PolyModulusDegree: CoeffModulus.MaxBitCount(8192) returns 218.
+ */
+ ulong polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.Create(
+ polyModulusDegree, new int[]{ 60, 40, 40, 60 });
+
+ /*
+ We choose the initial scale to be 2^40. At the last level, this leaves us
+ 60-40=20 bits of precision before the decimal point, and enough (roughly
+ 10-20 bits) of precision after the decimal point. Since our intermediate
+ primes are 40 bits (in fact, they are very close to 2^40), we can achieve
+ scale stabilization as described above.
+ */
+ double scale = Math.Pow(2.0, 40);
+
+ using SEALContext context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+ using RelinKeys relinKeys = keygen.RelinKeysLocal();
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ using CKKSEncoder encoder = new CKKSEncoder(context);
+ ulong slotCount = encoder.SlotCount;
+ Console.WriteLine($"Number of slots: {slotCount}");
+
+ List input = new List((int)slotCount);
+ double currPoint = 0, stepSize = 1.0 / (slotCount - 1);
+ for (ulong i = 0; i < slotCount; i++, currPoint += stepSize)
+ {
+ input.Add(currPoint);
+ }
+ Console.WriteLine("Input vector:");
+ Utilities.PrintVector(input, 3, 7);
+
+ Console.WriteLine("Evaluating polynomial PI*x^3 + 0.4x + 1 ...");
+
+ /*
+ We create plaintexts for PI, 0.4, and 1 using an overload of CKKSEncoder.Encode
+ that encodes the given floating-point value to every slot in the vector.
+ */
+ using Plaintext plainCoeff3 = new Plaintext(),
+ plainCoeff1 = new Plaintext(),
+ plainCoeff0 = new Plaintext();
+ encoder.Encode(3.14159265, scale, plainCoeff3);
+ encoder.Encode(0.4, scale, plainCoeff1);
+ encoder.Encode(1.0, scale, plainCoeff0);
+
+ using Plaintext xPlain = new Plaintext();
+ Utilities.PrintLine();
+ Console.WriteLine("Encode input vectors.");
+ encoder.Encode(input, scale, xPlain);
+ using Ciphertext x1Encrypted = new Ciphertext();
+ encryptor.Encrypt(xPlain, x1Encrypted);
+
+ /*
+ To compute x^3 we first compute x^2 and relinearize. However, the scale has
+ now grown to 2^80.
+ */
+ using Ciphertext x3Encrypted = new Ciphertext();
+ Utilities.PrintLine();
+ Console.WriteLine("Compute x^2 and relinearize:");
+ evaluator.Square(x1Encrypted, x3Encrypted);
+ evaluator.RelinearizeInplace(x3Encrypted, relinKeys);
+ Console.WriteLine(" + Scale of x^2 before rescale: {0} bits",
+ Math.Log(x3Encrypted.Scale, newBase: 2));
+
+ /*
+ Now rescale; in addition to a modulus switch, the scale is reduced down by
+ a factor equal to the prime that was switched away (40-bit prime). Hence, the
+ new scale should be close to 2^40. Note, however, that the scale is not equal
+ to 2^40: this is because the 40-bit prime is only close to 2^40.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Rescale x^2.");
+ evaluator.RescaleToNextInplace(x3Encrypted);
+ Console.WriteLine(" + Scale of x^2 after rescale: {0} bits",
+ Math.Log(x3Encrypted.Scale, newBase: 2));
+
+ /*
+ Now x3Encrypted is at a different level than x1Encrypted, which prevents us
+ from multiplying them to compute x^3. We could simply switch x1Encrypted to
+ the next parameters in the modulus switching chain. However, since we still
+ need to multiply the x^3 term with PI (plainCoeff3), we instead compute PI*x
+ first and multiply that with x^2 to obtain PI*x^3. To this end, we compute
+ PI*x and rescale it back from scale 2^80 to something close to 2^40.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute and rescale PI*x.");
+ using Ciphertext x1EncryptedCoeff3 = new Ciphertext();
+ evaluator.MultiplyPlain(x1Encrypted, plainCoeff3, x1EncryptedCoeff3);
+ Console.WriteLine(" + Scale of PI*x before rescale: {0} bits",
+ Math.Log(x1EncryptedCoeff3.Scale, newBase: 2));
+ evaluator.RescaleToNextInplace(x1EncryptedCoeff3);
+ Console.WriteLine(" + Scale of PI*x after rescale: {0} bits",
+ Math.Log(x1EncryptedCoeff3.Scale, newBase: 2));
+
+ /*
+ Since x3Encrypted and x1EncryptedCoeff3 have the same exact scale and use
+ the same encryption parameters, we can multiply them together. We write the
+ result to x3Encrypted, relinearize, and rescale. Note that again the scale
+ is something close to 2^40, but not exactly 2^40 due to yet another scaling
+ by a prime. We are down to the last level in the modulus switching chain.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute, relinearize, and rescale (PI*x)*x^2.");
+ evaluator.MultiplyInplace(x3Encrypted, x1EncryptedCoeff3);
+ evaluator.RelinearizeInplace(x3Encrypted, relinKeys);
+ Console.WriteLine(" + Scale of PI*x^3 before rescale: {0} bits",
+ Math.Log(x3Encrypted.Scale, newBase: 2));
+ evaluator.RescaleToNextInplace(x3Encrypted);
+ Console.WriteLine(" + Scale of PI*x^3 after rescale: {0} bits",
+ Math.Log(x3Encrypted.Scale, newBase: 2));
+
+ /*
+ Next we compute the degree one term. All this requires is one MultiplyPlain
+ with plainCoeff1. We overwrite x1Encrypted with the result.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute and rescale 0.4*x.");
+ evaluator.MultiplyPlainInplace(x1Encrypted, plainCoeff1);
+ Console.WriteLine(" + Scale of 0.4*x before rescale: {0} bits",
+ Math.Log(x1Encrypted.Scale, newBase: 2));
+ evaluator.RescaleToNextInplace(x1Encrypted);
+ Console.WriteLine(" + Scale of 0.4*x after rescale: {0} bits",
+ Math.Log(x1Encrypted.Scale, newBase: 2));
+
+ /*
+ Now we would hope to compute the sum of all three terms. However, there is
+ a serious problem: the encryption parameters used by all three terms are
+ different due to modulus switching from rescaling.
+
+ Encrypted addition and subtraction require that the scales of the inputs are
+ the same, and also that the encryption parameters (ParmsId) match. If there
+ is a mismatch, Evaluator will throw an exception.
+ */
+ Console.WriteLine();
+ Utilities.PrintLine();
+ Console.WriteLine("Parameters used by all three terms are different:");
+ Console.WriteLine(" + Modulus chain index for x3Encrypted: {0}",
+ context.GetContextData(x3Encrypted.ParmsId).ChainIndex);
+ Console.WriteLine(" + Modulus chain index for x1Encrypted: {0}",
+ context.GetContextData(x1Encrypted.ParmsId).ChainIndex);
+ Console.WriteLine(" + Modulus chain index for plainCoeff0: {0}",
+ context.GetContextData(plainCoeff0.ParmsId).ChainIndex);
+ Console.WriteLine();
+
+ /*
+ Let us carefully consider what the scales are at this point. We denote the
+ primes in coeff_modulus as P_0, P_1, P_2, P_3, in this order. P_3 is used as
+ the special modulus and is not involved in rescalings. After the computations
+ above the scales in ciphertexts are:
+
+ - Product x^2 has scale 2^80 and is at level 2;
+ - Product PI*x has scale 2^80 and is at level 2;
+ - We rescaled both down to scale 2^80/P2 and level 1;
+ - Product PI*x^3 has scale (2^80/P_2)^2;
+ - We rescaled it down to scale (2^80/P_2)^2/P_1 and level 0;
+ - Product 0.4*x has scale 2^80;
+ - We rescaled it down to scale 2^80/P_2 and level 1;
+ - The contant term 1 has scale 2^40 and is at level 2.
+
+ Although the scales of all three terms are approximately 2^40, their exact
+ values are different, hence they cannot be added together.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("The exact scales of all three terms are different:");
+ Console.WriteLine(" + Exact scale in PI*x^3: {0:0.0000000000}", x3Encrypted.Scale);
+ Console.WriteLine(" + Exact scale in 0.4*x: {0:0.0000000000}", x1Encrypted.Scale);
+ Console.WriteLine(" + Exact scale in 1: {0:0.0000000000}", plainCoeff0.Scale);
+ Console.WriteLine();
+
+ /*
+ There are many ways to fix this problem. Since P_2 and P_1 are really close
+ to 2^40, we can simply "lie" to Microsoft SEAL and set the scales to be the
+ same. For example, changing the scale of PI*x^3 to 2^40 simply means that we
+ scale the value of PI*x^3 by 2^120/(P_2^2*P_1), which is very close to 1.
+ This should not result in any noticeable error.
+
+ Another option would be to encode 1 with scale 2^80/P_2, do a MultiplyPlain
+ with 0.4*x, and finally rescale. In this case we would need to additionally
+ make sure to encode 1 with appropriate encryption parameters (ParmsId).
+
+ In this example we will use the first (simplest) approach and simply change
+ the scale of PI*x^3 and 0.4*x to 2^40.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Normalize scales to 2^40.");
+ x3Encrypted.Scale = Math.Pow(2.0, 40);
+ x1Encrypted.Scale = Math.Pow(2.0, 40);
+
+ /*
+ We still have a problem with mismatching encryption parameters. This is easy
+ to fix by using traditional modulus switching (no rescaling). CKKS supports
+ modulus switching just like the BFV scheme, allowing us to switch away parts
+ of the coefficient modulus when it is simply not needed.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Normalize encryption parameters to the lowest level.");
+ ParmsId lastParmsId = x3Encrypted.ParmsId;
+ evaluator.ModSwitchToInplace(x1Encrypted, lastParmsId);
+ evaluator.ModSwitchToInplace(plainCoeff0, lastParmsId);
+
+ /*
+ All three ciphertexts are now compatible and can be added.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Compute PI*x^3 + 0.4*x + 1.");
+ using Ciphertext encryptedResult = new Ciphertext();
+ evaluator.Add(x3Encrypted, x1Encrypted, encryptedResult);
+ evaluator.AddPlainInplace(encryptedResult, plainCoeff0);
+
+ /*
+ First print the true result.
+ */
+ using Plaintext plainResult = new Plaintext();
+ Utilities.PrintLine();
+ Console.WriteLine("Decrypt and decode PI * x ^ 3 + 0.4x + 1.");
+ Console.WriteLine(" + Expected result:");
+ List trueResult = new List(input.Count);
+ foreach (double x in input)
+ {
+ trueResult.Add((3.14159265 * x * x + 0.4) * x + 1);
+ }
+ Utilities.PrintVector(trueResult, 3, 7);
+
+ /*
+ We decrypt, decode, and print the result.
+ */
+ decryptor.Decrypt(encryptedResult, plainResult);
+ List result = new List();
+ encoder.Decode(plainResult, result);
+ Console.WriteLine(" + Computed result ...... Correct.");
+ Utilities.PrintVector(result, 3, 7);
+
+ /*
+ While we did not show any computations on complex numbers in these examples,
+ the CKKSEncoder would allow us to have done that just as easily. Additions
+ and multiplications of complex numbers behave just as one would expect.
+ */
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/5_Rotation.cs b/bigpiseal3.5.1/dotnet/examples/5_Rotation.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a9c04124bf820d8010fa950a44a1f32d7e54b669
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/5_Rotation.cs
@@ -0,0 +1,204 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using Microsoft.Research.SEAL;
+using System.Collections.Generic;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ /*
+ Both the BFV scheme (with BatchEncoder) as well as the CKKS scheme support native
+ vectorized computations on encrypted numbers. In addition to computing slot-wise,
+ it is possible to rotate the encrypted vectors cyclically.
+ */
+ private static void ExampleRotationBFV()
+ {
+ Utilities.PrintExampleBanner("Example: Rotation / Rotation in BFV");
+
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+
+ ulong polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ parms.PlainModulus = PlainModulus.Batching(polyModulusDegree, 20);
+
+ using SEALContext context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+ using RelinKeys relinKeys = keygen.RelinKeysLocal();
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ using BatchEncoder batchEncoder = new BatchEncoder(context);
+ ulong slotCount = batchEncoder.SlotCount;
+ ulong rowSize = slotCount / 2;
+ Console.WriteLine($"Plaintext matrix row size: {rowSize}");
+
+ ulong[] podMatrix = new ulong[slotCount];
+ podMatrix[0] = 0;
+ podMatrix[1] = 1;
+ podMatrix[2] = 2;
+ podMatrix[3] = 3;
+ podMatrix[rowSize] = 4;
+ podMatrix[rowSize + 1] = 5;
+ podMatrix[rowSize + 2] = 6;
+ podMatrix[rowSize + 3] = 7;
+
+ Console.WriteLine("Input plaintext matrix:");
+ Utilities.PrintMatrix(podMatrix, (int)rowSize);
+ Console.WriteLine();
+
+ /*
+ First we use BatchEncoder to encode the matrix into a plaintext. We encrypt
+ the plaintext as usual.
+ */
+ Utilities.PrintLine();
+ using Plaintext plainMatrix = new Plaintext();
+ Console.WriteLine("Encode and encrypt.");
+ batchEncoder.Encode(podMatrix, plainMatrix);
+ using Ciphertext encryptedMatrix = new Ciphertext();
+ encryptor.Encrypt(plainMatrix, encryptedMatrix);
+ Console.WriteLine(" + Noise budget in fresh encryption: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedMatrix));
+ Console.WriteLine();
+
+ /*
+ Rotations require yet another type of special key called `Galois keys'. These
+ are easily obtained from the KeyGenerator.
+ */
+ using GaloisKeys galKeys = keygen.GaloisKeysLocal();
+
+ /*
+ Now rotate both matrix rows 3 steps to the left, decrypt, decode, and print.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Rotate rows 3 steps left.");
+ evaluator.RotateRowsInplace(encryptedMatrix, 3, galKeys);
+ using Plaintext plainResult = new Plaintext();
+ Console.WriteLine(" + Noise budget after rotation: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedMatrix));
+ Console.WriteLine(" + Decrypt and decode ...... Correct.");
+ decryptor.Decrypt(encryptedMatrix, plainResult);
+ List podResult = new List();
+ batchEncoder.Decode(plainResult, podResult);
+ Utilities.PrintMatrix(podResult, (int)rowSize);
+
+ /*
+ We can also rotate the columns, i.e., swap the rows.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Rotate columns.");
+ evaluator.RotateColumnsInplace(encryptedMatrix, galKeys);
+ Console.WriteLine(" + Noise budget after rotation: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedMatrix));
+ Console.WriteLine(" + Decrypt and decode ...... Correct.");
+ decryptor.Decrypt(encryptedMatrix, plainResult);
+ batchEncoder.Decode(plainResult, podResult);
+ Utilities.PrintMatrix(podResult, (int)rowSize);
+
+ /*
+ Finally, we rotate the rows 4 steps to the right, decrypt, decode, and print.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine("Rotate rows 4 steps right.");
+ evaluator.RotateRowsInplace(encryptedMatrix, -4, galKeys);
+ Console.WriteLine(" + Noise budget after rotation: {0} bits",
+ decryptor.InvariantNoiseBudget(encryptedMatrix));
+ Console.WriteLine(" + Decrypt and decode ...... Correct.");
+ decryptor.Decrypt(encryptedMatrix, plainResult);
+ batchEncoder.Decode(plainResult, podResult);
+ Utilities.PrintMatrix(podResult, (int)rowSize);
+
+ /*
+ Note that rotations do not consume any noise budget. However, this is only
+ the case when the special prime is at least as large as the other primes. The
+ same holds for relinearization. Microsoft SEAL does not require that the
+ special prime is of any particular size, so ensuring this is the case is left
+ for the user to do.
+ */
+ }
+
+ private static void ExampleRotationCKKS()
+ {
+ Utilities.PrintExampleBanner("Example: Rotation / Rotation in CKKS");
+
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+
+ ulong polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.Create(
+ polyModulusDegree, new int[] { 40, 40, 40, 40, 40 });
+
+ using SEALContext context = new SEALContext(parms);
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using PublicKey publicKey = keygen.PublicKey;
+ using SecretKey secretKey = keygen.SecretKey;
+ using RelinKeys relinKeys = keygen.RelinKeysLocal();
+ using GaloisKeys galKeys = keygen.GaloisKeysLocal();
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+
+ using CKKSEncoder ckksEncoder = new CKKSEncoder(context);
+
+ ulong slotCount = ckksEncoder.SlotCount;
+ Console.WriteLine($"Number of slots: {slotCount}");
+
+ List input = new List((int)slotCount);
+ double currPoint = 0, stepSize = 1.0 / (slotCount - 1);
+ for (ulong i = 0; i < slotCount; i++, currPoint += stepSize)
+ {
+ input.Add(currPoint);
+ }
+ Console.WriteLine("Input vector:");
+ Utilities.PrintVector(input, 3, 7);
+
+ double scale = Math.Pow(2.0, 50);
+
+ Utilities.PrintLine();
+ Console.WriteLine("Encode and encrypt.");
+ using Plaintext plain = new Plaintext();
+ ckksEncoder.Encode(input, scale, plain);
+ using Ciphertext encrypted = new Ciphertext();
+ encryptor.Encrypt(plain, encrypted);
+
+ using Ciphertext rotated = new Ciphertext();
+ Utilities.PrintLine();
+ Console.WriteLine("Rotate 2 steps left.");
+ evaluator.RotateVector(encrypted, 2, galKeys, rotated);
+ Console.WriteLine(" + Decrypt and decode ...... Correct.");
+ decryptor.Decrypt(encrypted, plain);
+ List result = new List();
+ ckksEncoder.Decode(plain, result);
+ Utilities.PrintVector(result, 3, 7);
+
+ /*
+ With the CKKS scheme it is also possible to evaluate a complex conjugation on
+ a vector of encrypted complex numbers, using Evaluator.ComplexConjugate. This
+ is in fact a kind of rotation, and requires also Galois keys.
+ */
+ }
+
+ private static void ExampleRotation()
+ {
+ Utilities.PrintExampleBanner("Example: Rotation");
+
+ /*
+ Run all rotation examples.
+ */
+ ExampleRotationBFV();
+ ExampleRotationCKKS();
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/6_Serialization.cs b/bigpiseal3.5.1/dotnet/examples/6_Serialization.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fe1ec9b7f77a86a99fa95f95f7511004899fd3e4
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/6_Serialization.cs
@@ -0,0 +1,423 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using Microsoft.Research.SEAL;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ /*
+ In this example we show how serialization works in Microsoft SEAL. Specifically,
+ we present important concepts that enable the user to optimize the data size when
+ communicating ciphertexts and keys for outsourced computation. Unlike the previous
+ examples, we organize this one in a client-server style for maximal clarity. The
+ server selects encryption parameters, the client generates keys, the server does
+ the encrypted computation, and the client decrypts.
+ */
+ private static void ExampleSerialization()
+ {
+ Utilities.PrintExampleBanner("Example: Serialization");
+
+ /*
+ We require ZLIB support for this example to be available.
+ */
+ if (!Serialization.IsSupportedComprMode(ComprModeType.Deflate))
+ {
+ Console.WriteLine("ZLIB support is not enabled; this example is not available.");
+ Console.WriteLine();
+ return;
+ }
+
+ /*
+ To simulate client-server interaction, we set up a shared C# stream. In real
+ use-cases this can be a network stream, a filestream, or any shared resource.
+
+ It is critical to note that all data serialized by Microsoft SEAL is in binary
+ form, so it is not meaningful to print the data as ASCII characters. Encodings
+ such as Base64 would increase the data size, which is already a bottleneck in
+ homomorphic encryption. Hence, serialization into text is not supported or
+ recommended.
+
+ In this example we use a couple of shared MemoryStreams.
+ */
+ MemoryStream parmsStream = new MemoryStream();
+ MemoryStream dataStream = new MemoryStream();
+ MemoryStream skStream = new MemoryStream();
+
+ /*
+ The server first determines the computation and sets encryption parameters
+ accordingly.
+ */
+ {
+ ulong polyModulusDegree = 8192;
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.Create(
+ polyModulusDegree, new int[]{ 50, 20, 50 });
+
+ /*
+ Serialization of the encryption parameters to our shared stream is very
+ simple with the EncryptionParameters.Save function.
+ */
+ long size = parms.Save(parmsStream);
+
+ /*
+ Seek the parmsStream head back to beginning of the stream.
+ */
+ parmsStream.Seek(0, SeekOrigin.Begin);
+
+ /*
+ The return value of this function is the actual byte count of data written
+ to the stream.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine($"EncryptionParameters: wrote {size} bytes");
+
+ /*
+ Before moving on, we will take some time to discuss further options in
+ serialization. These will become particularly important when the user
+ needs to optimize communication and storage sizes.
+ */
+
+ /*
+ It is possible to enable or disable ZLIB ("deflate") compression for
+ serialization by providing EncryptionParameters.Save with the desired
+ compression mode as in the following examples:
+
+ long size = parms.Save(sharedStream, ComprModeType.None);
+ long size = parms.Save(sharedStream, ComprModeType.Deflate);
+
+ If Microsoft SEAL is compiled with ZLIB support, the default is to use
+ ComprModeType.Deflate, so to instead disable compression one would use
+ the first version of the two.
+ */
+
+ /*
+ In many cases, when working with fixed size memory, it is necessary
+ to know ahead of time an upper bound on the serialized data size to
+ allocate enough memory. This information is returned by the
+ EncryptionParameters.SaveSize function. This function accepts the
+ desired compression mode, with ComprModeType.Deflate being the default
+ when Microsoft SEAL is compiled with ZLIB support.
+
+ In more detail, the output of EncryptionParameters.SaveSize is as follows:
+
+ - Exact buffer size required for ComprModeType.None;
+ - Upper bound on the size required for ComprModeType.Deflate.
+
+ As we can see from the print-out, the sizes returned by these functions
+ are significantly larger than the compressed size written into the shared
+ stream in the beginning. This is normal: compression yielded a significant
+ improvement in the data size, yet it is hard to estimate the size of the
+ compressed data.
+ */
+ Utilities.PrintLine();
+ Console.Write("EncryptionParameters: data size upper bound (ComprModeType.None): ");
+ Console.WriteLine(parms.SaveSize(ComprModeType.None));
+ Console.Write(" ");
+ Console.Write("EncryptionParameters: data size upper bound (ComprModeType.Deflate): ");
+ Console.WriteLine(parms.SaveSize(ComprModeType.Deflate));
+
+ /*
+ As an example, we now serialize the encryption parameters to a fixed
+ size buffer.
+ */
+ MemoryStream buffer = new MemoryStream(new byte[parms.SaveSize()]);
+ parms.Save(buffer);
+
+ /*
+ To illustrate deserialization, we load back the encryption parameters
+ from our buffer into another instance of EncryptionParameters. First
+ we need to seek our stream back to the beginning.
+ */
+ buffer.Seek(0, SeekOrigin.Begin);
+ using EncryptionParameters parms2 = new EncryptionParameters();
+ parms2.Load(buffer);
+
+ /*
+ We can check that the saved and loaded encryption parameters indeed match.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine($"EncryptionParameters: parms == parms2: {parms.Equals(parms2)}");
+ }
+
+ /*
+ Client starts by loading the encryption parameters, sets up the SEALContext,
+ and creates the required keys.
+ */
+ {
+ using EncryptionParameters parms = new EncryptionParameters();
+ parms.Load(parmsStream);
+
+ /*
+ Seek the parmsStream head back to beginning of the stream because we
+ will use the same stream to read the parameters repeatedly.
+ */
+ parmsStream.Seek(0, SeekOrigin.Begin);
+
+ using SEALContext context = new SEALContext(parms);
+
+ using KeyGenerator keygen = new KeyGenerator(context);
+ using SecretKey sk = keygen.SecretKey;
+ using PublicKey pk = keygen.PublicKey;
+
+ /*
+ We need to save the secret key so we can decrypt later.
+ */
+ sk.Save(skStream);
+ skStream.Seek(0, SeekOrigin.Begin);
+
+ /*
+ In this example we will also use relinearization keys. For realinearization
+ and Galois keys the KeyGenerator.RelinKeys and KeyGenerator.GaloisKeys
+ functions return special Serializable objects. These objects are meant
+ to be serialized and never used locally. On the other hand, for local use
+ of RelinKeys and GaloisKeys, the functions KeyGenerator.RelinKeysLocal
+ and KeyGenerator.GaloisKeysLocal can be used to create the RelinKeys
+ and GaloisKeys objects directly. The difference is that the Serializable
+ objects contain a partly seeded version of the RelinKeys (or GaloisKeys)
+ that will result in a significantly smaller size when serialized. Using
+ this method has no impact on security. Such seeded RelinKeys (GaloisKeys)
+ must be expanded before being used in computations; this is automatically
+ done by deserialization.
+ */
+ using Serializable rlk = keygen.RelinKeys();
+
+ /*
+ Before continuing, we demonstrate the significant space saving from this
+ method.
+ */
+ long sizeRlk = rlk.Save(dataStream);
+
+ using RelinKeys rlkLocal = keygen.RelinKeysLocal();
+ long sizeRlkLocal = rlkLocal.Save(dataStream);
+
+ /*
+ Now compare the serialized sizes of rlk and rlkLocal.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine($"Serializable: wrote {sizeRlk} bytes");
+ Console.Write(" ");
+ Console.WriteLine($"RelinKeys (local): wrote {sizeRlkLocal} bytes");
+
+ /*
+ Seek back in dataStream to where rlk data ended, i.e., sizeRlkLocal
+ bytes backwards from current position.
+ */
+ dataStream.Seek(-sizeRlkLocal, SeekOrigin.Current);
+
+ /*
+ Next set up the CKKSEncoder and Encryptor, and encrypt some numbers.
+ */
+ double scale = Math.Pow(2.0, 20);
+ CKKSEncoder encoder = new CKKSEncoder(context);
+ using Plaintext plain1 = new Plaintext(),
+ plain2 = new Plaintext();
+ encoder.Encode(2.3, scale, plain1);
+ encoder.Encode(4.5, scale, plain2);
+
+ using Encryptor encryptor = new Encryptor(context, pk);
+ using Ciphertext encrypted1 = new Ciphertext(),
+ encrypted2 = new Ciphertext();
+ encryptor.Encrypt(plain1, encrypted1);
+ encryptor.Encrypt(plain2, encrypted2);
+
+ /*
+ Now, we could serialize both encrypted1 and encrypted2 to dataStream
+ using Ciphertext.Save. However, for this example, we demonstrate another
+ size-saving trick that can come in handy.
+
+ As you noticed, we set up the Encryptor using the public key. Clearly this
+ indicates that the CKKS scheme is a public-key encryption scheme. However,
+ both BFV and CKKS can operate also in a symmetric-key mode. This can be
+ beneficial when the public-key functionality is not exactly needed, like
+ in simple outsourced computation scenarios. The benefit is that in these
+ cases it is possible to produce ciphertexts that are partly seeded, hence
+ significantly smaller. Such ciphertexts must be expanded before being used
+ in computations; this is automatically done by deserialization.
+
+ To use symmetric-key encryption, we need to set up the Encryptor with the
+ secret key instead.
+ */
+ using Encryptor symEncryptor = new Encryptor(context, sk);
+ using Serializable symEncrypted1 = symEncryptor.EncryptSymmetric(plain1);
+ using Serializable symEncrypted2 = symEncryptor.EncryptSymmetric(plain2);
+
+ /*
+ Before continuing, we demonstrate the significant space saving from this
+ method.
+ */
+ long sizeSymEncrypted1 = symEncrypted1.Save(dataStream);
+ long sizeEncrypted1 = encrypted1.Save(dataStream);
+
+ /*
+ Now compare the serialized sizes of encrypted1 and symEncrypted1.
+ */
+ Utilities.PrintLine();
+ Console.Write("Serializable (symmetric-key): ");
+ Console.WriteLine($"wrote {sizeSymEncrypted1} bytes");
+ Console.Write(" ");
+ Console.WriteLine($"Ciphertext (public-key): wrote {sizeEncrypted1} bytes");
+
+ /*
+ Seek back in dataStream to where symEncrypted1 data ended, i.e.,
+ sizeEncrypted1 bytes backwards from current position and write
+ symEncrypted2 right after symEncrypted1.
+ */
+ dataStream.Seek(-sizeEncrypted1, SeekOrigin.Current);
+ symEncrypted2.Save(dataStream);
+ dataStream.Seek(0, SeekOrigin.Begin);
+
+ /*
+ We have seen how using KeyGenerator.RelinKeys (KeyGenerator.GaloisKeys)
+ can result in huge space savings over the local variants when the objects
+ are not needed for local use. We have seen how symmetric-key encryption
+ can be used to achieve much smaller ciphertext sizes when the public-key
+ functionality is not needed.
+
+ We would also like to draw attention to the fact there we could easily
+ serialize multiple Microsoft SEAL objects sequentially in a stream. Each
+ object writes its own size into the stream, so deserialization knows
+ exactly how many bytes to read. We will see this working next.
+
+ Finally, we would like to point out that none of these methods provide any
+ space savings unless Microsoft SEAL is compiled with ZLIB support, or when
+ serialized with ComprModeType.None.
+ */
+ }
+
+ /*
+ The server can now compute on the encrypted data. We will recreate the
+ SEALContext and set up an Evaluator here.
+ */
+ {
+ using EncryptionParameters parms = new EncryptionParameters();
+ parms.Load(parmsStream);
+ parmsStream.Seek(0, SeekOrigin.Begin);
+ using SEALContext context = new SEALContext(parms);
+
+ using Evaluator evaluator = new Evaluator(context);
+
+ /*
+ Next we need to load relinearization keys and the ciphertexts from our
+ dataStream.
+ */
+ using RelinKeys rlk = new RelinKeys();
+ using Ciphertext encrypted1 = new Ciphertext(),
+ encrypted2 = new Ciphertext();
+
+ /*
+ Deserialization is as easy as serialization.
+ */
+ rlk.Load(context, dataStream);
+ encrypted1.Load(context, dataStream);
+ encrypted2.Load(context, dataStream);
+
+ /*
+ Compute the product, rescale, and relinearize.
+ */
+ using Ciphertext encryptedProd = new Ciphertext();
+ evaluator.Multiply(encrypted1, encrypted2, encryptedProd);
+ evaluator.RelinearizeInplace(encryptedProd, rlk);
+ evaluator.RescaleToNextInplace(encryptedProd);
+
+ /*
+ We use dataStream to communicate encryptedProd back to the client. There
+ is no way to save the encryptedProd as Serializable even
+ though it is still a symmetric-key encryption: only freshly encrypted
+ ciphertexts can be seeded. Note how the size of the result ciphertext is
+ smaller than the size of a fresh ciphertext because it is at a lower level
+ due to the rescale operation.
+ */
+ dataStream.Seek(0, SeekOrigin.Begin);
+ long sizeEncryptedProd = encryptedProd.Save(dataStream);
+ dataStream.Seek(0, SeekOrigin.Begin);
+
+ Utilities.PrintLine();
+ Console.Write($"Ciphertext (symmetric-key): ");
+ Console.WriteLine($"wrote {sizeEncryptedProd} bytes");
+ }
+
+ /*
+ In the final step the client decrypts the result.
+ */
+ {
+ using EncryptionParameters parms = new EncryptionParameters();
+ parms.Load(parmsStream);
+ parmsStream.Seek(0, SeekOrigin.Begin);
+ using SEALContext context = new SEALContext(parms);
+
+ /*
+ Load back the secret key from skStream.
+ */
+ using SecretKey sk = new SecretKey();
+ sk.Load(context, skStream);
+ using Decryptor decryptor = new Decryptor(context, sk);
+ using CKKSEncoder encoder = new CKKSEncoder(context);
+
+ using Ciphertext encryptedResult = new Ciphertext();
+ encryptedResult.Load(context, dataStream);
+
+ using Plaintext plainResult = new Plaintext();
+ decryptor.Decrypt(encryptedResult, plainResult);
+ List result = new List();
+ encoder.Decode(plainResult, result);
+
+ Utilities.PrintLine();
+ Console.WriteLine("Result: ");
+ Utilities.PrintVector(result, 3, 7);
+ }
+
+ /*
+ Finally, we give a little bit more explanation of the structure of data
+ serialized by Microsoft SEAL. Serialized data always starts with a 16-byte
+ SEALHeader struct, as defined in dotnet/src/Serialization.cs, and is
+ followed by the possibly compressed data for the object.
+
+ A SEALHeader contains the following data:
+
+ [offset 0] 2-byte magic number 0xA15E (Serialization.SEALMagic)
+ [offset 2] 1-byte indicating the header size in bytes (always 16)
+ [offset 3] 1-byte indicating the Microsoft SEAL major version number
+ [offset 4] 1-byte indicating the Microsoft SEAL minor version number
+ [offset 5] 1-byte indicating the compression mode type
+ [offset 6] 2-byte reserved field (unused)
+ [offset 8] 8-byte size in bytes of the serialized data, including the header
+
+ Currently Microsoft SEAL supports only little-endian systems.
+
+ As an example, we demonstrate the SEALHeader created by saving a plaintext.
+ Note that the SEALHeader is never compressed, so there is no need to specify
+ the compression mode.
+ */
+ using Plaintext pt = new Plaintext("1x^2 + 3");
+ MemoryStream stream = new MemoryStream();
+ long dataSize = pt.Save(stream);
+
+ /*
+ Seek the stream head back to beginning of the stream.
+ */
+ stream.Seek(0, SeekOrigin.Begin);
+
+ /*
+ We can now load just the SEALHeader back from the stream as follows.
+ */
+ Serialization.SEALHeader header = new Serialization.SEALHeader();
+ Serialization.LoadHeader(stream, header);
+
+ /*
+ Now confirm that the size of data written to stream matches with what is
+ indicated by the SEALHeader.
+ */
+ Utilities.PrintLine();
+ Console.WriteLine($"Size written to stream: {dataSize} bytes");
+ Console.Write(" ");
+ Console.WriteLine($"Size indicated in SEALHeader: {header.Size} bytes");
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/7_Performance.cs b/bigpiseal3.5.1/dotnet/examples/7_Performance.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7bc10d9a711a1cdd155825606a04ea3d56c2d01a
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/7_Performance.cs
@@ -0,0 +1,785 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using Microsoft.Research.SEAL;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ private static void BFVPerformanceTest(SEALContext context)
+ {
+ Stopwatch timer;
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ using EncryptionParameters parms = context.FirstContextData.Parms;
+ using Modulus plainModulus = parms.PlainModulus;
+ ulong polyModulusDegree = parms.PolyModulusDegree;
+
+ Console.Write("Generating secret/public keys: ");
+ using KeyGenerator keygen = new KeyGenerator(context);
+ Console.WriteLine("Done");
+
+ using SecretKey secretKey = keygen.SecretKey;
+ using PublicKey publicKey = keygen.PublicKey;
+
+ Func GetRelinKeys = () => {
+ if (context.UsingKeyswitching)
+ {
+ /*
+ Generate relinearization keys.
+ */
+ Console.Write("Generating relinearization keys: ");
+ timer = Stopwatch.StartNew();
+ RelinKeys result = keygen.RelinKeysLocal();
+ int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
+ Console.WriteLine($"Done [{micros} microseconds]");
+ return result;
+ }
+ else
+ {
+ return null;
+ }
+ };
+
+ Func GetGaloisKeys = () => {
+ if (context.UsingKeyswitching)
+ {
+ if (!context.KeyContextData.Qualifiers.UsingBatching)
+ {
+ Console.WriteLine("Given encryption parameters do not support batching.");
+ return null;
+ }
+
+ /*
+ Generate Galois keys. In larger examples the Galois keys can use a lot of
+ memory, which can be a problem in constrained systems. The user should
+ try some of the larger runs of the test and observe their effect on the
+ memory pool allocation size. The key generation can also take a long time,
+ as can be observed from the print-out.
+ */
+ Console.Write($"Generating Galois keys: ");
+ timer = Stopwatch.StartNew();
+ GaloisKeys result = keygen.GaloisKeysLocal();
+ int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
+ Console.WriteLine($"Done [{micros} microseconds]");
+ return result;
+ }
+ else
+ {
+ return null;
+ }
+ };
+
+ using RelinKeys relinKeys = GetRelinKeys();
+ using GaloisKeys galKeys = GetGaloisKeys();
+
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using BatchEncoder batchEncoder = new BatchEncoder(context);
+ using IntegerEncoder encoder = new IntegerEncoder(context);
+
+ /*
+ These will hold the total times used by each operation.
+ */
+ Stopwatch timeBatchSum = new Stopwatch();
+ Stopwatch timeUnbatchSum = new Stopwatch();
+ Stopwatch timeEncryptSum = new Stopwatch();
+ Stopwatch timeDecryptSum = new Stopwatch();
+ Stopwatch timeAddSum = new Stopwatch();
+ Stopwatch timeMultiplySum = new Stopwatch();
+ Stopwatch timeMultiplyPlainSum = new Stopwatch();
+ Stopwatch timeSquareSum = new Stopwatch();
+ Stopwatch timeRelinearizeSum = new Stopwatch();
+ Stopwatch timeRotateRowsOneStepSum = new Stopwatch();
+ Stopwatch timeRotateRowsRandomSum = new Stopwatch();
+ Stopwatch timeRotateColumnsSum = new Stopwatch();
+
+ /*
+ How many times to run the test?
+ */
+ int count = 10;
+
+ /*
+ Populate a vector of values to batch.
+ */
+ ulong slotCount = batchEncoder.SlotCount;
+ ulong[] podValues = new ulong[slotCount];
+ Random rnd = new Random();
+ for (ulong i = 0; i < batchEncoder.SlotCount; i++)
+ {
+ podValues[i] = (ulong)rnd.Next() % plainModulus.Value;
+ }
+
+ Console.Write("Running tests ");
+ for (int i = 0; i < count; i++)
+ {
+ /*
+ [Batching]
+ There is nothing unusual here. We batch our random plaintext matrix
+ into the polynomial. Note how the plaintext we create is of the exactly
+ right size so unnecessary reallocations are avoided.
+ */
+ using Plaintext plain = new Plaintext(parms.PolyModulusDegree, 0);
+ timeBatchSum.Start();
+ batchEncoder.Encode(podValues, plain);
+ timeBatchSum.Stop();
+
+ /*
+ [Unbatching]
+ We unbatch what we just batched.
+ */
+ List podList = new List((int)slotCount);
+ timeUnbatchSum.Start();
+ batchEncoder.Decode(plain, podList);
+ timeUnbatchSum.Stop();
+ if (!podList.SequenceEqual(podValues))
+ {
+ throw new InvalidOperationException("Batch/unbatch failed. Something is wrong.");
+ }
+
+ /*
+ [Encryption]
+ We make sure our ciphertext is already allocated and large enough
+ to hold the encryption with these encryption parameters. We encrypt
+ our random batched matrix here.
+ */
+ using Ciphertext encrypted = new Ciphertext(context);
+ timeEncryptSum.Start();
+ encryptor.Encrypt(plain, encrypted);
+ timeEncryptSum.Stop();
+
+ /*
+ [Decryption]
+ We decrypt what we just encrypted.
+ */
+ using Plaintext plain2 = new Plaintext(polyModulusDegree, 0);
+ timeDecryptSum.Start();
+ decryptor.Decrypt(encrypted, plain2);
+ timeDecryptSum.Stop();
+ if (!plain2.Equals(plain))
+ {
+ throw new InvalidOperationException("Encrypt/decrypt failed. Something is wrong.");
+ }
+
+ /*
+ [Add]
+ We create two ciphertexts and perform a few additions with them.
+ */
+ using Ciphertext encrypted1 = new Ciphertext(context);
+ encryptor.Encrypt(encoder.Encode(i), encrypted1);
+ using Ciphertext encrypted2 = new Ciphertext(context);
+ encryptor.Encrypt(encoder.Encode(i + 1), encrypted2);
+
+ timeAddSum.Start();
+ evaluator.AddInplace(encrypted1, encrypted1);
+ evaluator.AddInplace(encrypted2, encrypted2);
+ evaluator.AddInplace(encrypted1, encrypted2);
+ timeAddSum.Stop();
+
+ /*
+ [Multiply]
+ We multiply two ciphertexts. Since the size of the result will be 3,
+ and will overwrite the first argument, we reserve first enough memory
+ to avoid reallocating during multiplication.
+ */
+ encrypted1.Reserve(3);
+ timeMultiplySum.Start();
+ evaluator.MultiplyInplace(encrypted1, encrypted2);
+ timeMultiplySum.Stop();
+
+ /*
+ [Multiply Plain]
+ We multiply a ciphertext with a random plaintext. Recall that
+ MultiplyPlain does not change the size of the ciphertext so we use
+ encrypted2 here.
+ */
+ timeMultiplyPlainSum.Start();
+ evaluator.MultiplyPlainInplace(encrypted2, plain);
+ timeMultiplyPlainSum.Stop();
+
+ /*
+ [Square]
+ We continue to use encrypted2. Now we square it; this should be
+ faster than generic homomorphic multiplication.
+ */
+ timeSquareSum.Start();
+ evaluator.SquareInplace(encrypted2);
+ timeSquareSum.Stop();
+
+ if (context.UsingKeyswitching)
+ {
+ /*
+ [Relinearize]
+ Time to get back to encrypted1. We now relinearize it back
+ to size 2. Since the allocation is currently big enough to
+ contain a ciphertext of size 3, no costly reallocations are
+ needed in the process.
+ */
+ timeRelinearizeSum.Start();
+ evaluator.RelinearizeInplace(encrypted1, relinKeys);
+ timeRelinearizeSum.Stop();
+
+ /*
+ [Rotate Rows One Step]
+ We rotate matrix rows by one step left and measure the time.
+ */
+ timeRotateRowsOneStepSum.Start();
+ evaluator.RotateRowsInplace(encrypted, 1, galKeys);
+ evaluator.RotateRowsInplace(encrypted, -1, galKeys);
+ timeRotateRowsOneStepSum.Stop();
+
+ /*
+ [Rotate Rows Random]
+ We rotate matrix rows by a random number of steps. This is much more
+ expensive than rotating by just one step.
+ */
+ int rowSize = (int)batchEncoder.SlotCount / 2;
+ int randomRotation = rnd.Next() % rowSize;
+ timeRotateRowsRandomSum.Start();
+ evaluator.RotateRowsInplace(encrypted, randomRotation, galKeys);
+ timeRotateRowsRandomSum.Stop();
+
+ /*
+ [Rotate Columns]
+ Nothing surprising here.
+ */
+ timeRotateColumnsSum.Start();
+ evaluator.RotateColumnsInplace(encrypted, galKeys);
+ timeRotateColumnsSum.Stop();
+ }
+
+
+ /*
+ Print a dot to indicate progress.
+ */
+ Console.Write(".");
+ Console.Out.Flush();
+ }
+
+ Console.WriteLine(" Done");
+ Console.WriteLine();
+ Console.Out.Flush();
+
+ int avgBatch = (int)(timeBatchSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgUnbatch = (int)(timeUnbatchSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgEncrypt = (int)(timeEncryptSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgDecrypt = (int)(timeDecryptSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgAdd = (int)(timeAddSum.Elapsed.TotalMilliseconds * 1000 / (3 * count));
+ int avgMultiply = (int)(timeMultiplySum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgMultiplyPlain = (int)(timeMultiplyPlainSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgSquare = (int)(timeSquareSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgRelinearize = (int)(timeRelinearizeSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgRotateRowsOneStep = (int)(timeRotateRowsOneStepSum.Elapsed.TotalMilliseconds * 1000 / (2 * count));
+ int avgRotateRowsRandom = (int)(timeRotateRowsRandomSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgRotateColumns = (int)(timeRotateColumnsSum.Elapsed.TotalMilliseconds * 1000 / count);
+
+ Console.WriteLine($"Average batch: {avgBatch} microseconds");
+ Console.WriteLine($"Average unbatch: {avgUnbatch} microseconds");
+ Console.WriteLine($"Average encrypt: {avgEncrypt} microseconds");
+ Console.WriteLine($"Average decrypt: {avgDecrypt} microseconds");
+ Console.WriteLine($"Average add: {avgAdd} microseconds");
+ Console.WriteLine($"Average multiply: {avgMultiply} microseconds");
+ Console.WriteLine($"Average multiply plain: {avgMultiplyPlain} microseconds");
+ Console.WriteLine($"Average square: {avgSquare} microseconds");
+ if (context.UsingKeyswitching)
+ {
+ Console.WriteLine($"Average relinearize: {avgRelinearize} microseconds");
+ Console.WriteLine($"Average rotate rows one step: {avgRotateRowsOneStep} microseconds");
+ Console.WriteLine($"Average rotate rows random: {avgRotateRowsRandom} microseconds");
+ Console.WriteLine($"Average rotate columns: {avgRotateColumns} microseconds");
+ }
+ Console.Out.Flush();
+ }
+
+ private static void CKKSPerformanceTest(SEALContext context)
+ {
+ Stopwatch timer;
+ Utilities.PrintParameters(context);
+ Console.WriteLine();
+
+ using EncryptionParameters parms = context.FirstContextData.Parms;
+ ulong polyModulusDegree = parms.PolyModulusDegree;
+
+ Console.Write("Generating secret/public keys: ");
+ using KeyGenerator keygen = new KeyGenerator(context);
+ Console.WriteLine("Done");
+
+ using SecretKey secretKey = keygen.SecretKey;
+ using PublicKey publicKey = keygen.PublicKey;
+
+ Func GetRelinKeys = () => {
+ if (context.UsingKeyswitching)
+ {
+ /*
+ Generate relinearization keys.
+ */
+ Console.Write("Generating relinearization keys: ");
+ timer = Stopwatch.StartNew();
+ RelinKeys result = keygen.RelinKeysLocal();
+ int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
+ Console.WriteLine($"Done [{micros} microseconds]");
+ return result;
+ }
+ else
+ {
+ return null;
+ }
+ };
+
+ Func GetGaloisKeys = () => {
+ if (context.UsingKeyswitching)
+ {
+ if (!context.KeyContextData.Qualifiers.UsingBatching)
+ {
+ Console.WriteLine("Given encryption parameters do not support batching.");
+ return null;
+ }
+
+ /*
+ Generate Galois keys. In larger examples the Galois keys can use a lot of
+ memory, which can be a problem in constrained systems. The user should
+ try some of the larger runs of the test and observe their effect on the
+ memory pool allocation size. The key generation can also take a long time,
+ as can be observed from the print-out.
+ */
+ Console.Write($"Generating Galois keys: ");
+ timer = Stopwatch.StartNew();
+ GaloisKeys result = keygen.GaloisKeysLocal();
+ int micros = (int)(timer.Elapsed.TotalMilliseconds * 1000);
+ Console.WriteLine($"Done [{micros} microseconds]");
+ return result;
+ }
+ else
+ {
+ return null;
+ }
+ };
+
+ using RelinKeys relinKeys = GetRelinKeys();
+ using GaloisKeys galKeys = GetGaloisKeys();
+
+ using Encryptor encryptor = new Encryptor(context, publicKey);
+ using Decryptor decryptor = new Decryptor(context, secretKey);
+ using Evaluator evaluator = new Evaluator(context);
+ using CKKSEncoder ckksEncoder = new CKKSEncoder(context);
+
+ Stopwatch timeEncodeSum = new Stopwatch();
+ Stopwatch timeDecodeSum = new Stopwatch();
+ Stopwatch timeEncryptSum = new Stopwatch();
+ Stopwatch timeDecryptSum = new Stopwatch();
+ Stopwatch timeAddSum = new Stopwatch();
+ Stopwatch timeMultiplySum = new Stopwatch();
+ Stopwatch timeMultiplyPlainSum = new Stopwatch();
+ Stopwatch timeSquareSum = new Stopwatch();
+ Stopwatch timeRelinearizeSum = new Stopwatch();
+ Stopwatch timeRescaleSum = new Stopwatch();
+ Stopwatch timeRotateOneStepSum = new Stopwatch();
+ Stopwatch timeRotateRandomSum = new Stopwatch();
+ Stopwatch timeConjugateSum = new Stopwatch();
+
+ Random rnd = new Random();
+
+ /*
+ How many times to run the test?
+ */
+ int count = 10;
+
+ /*
+ Populate a vector of floating-point values to batch.
+ */
+ ulong slotCount = ckksEncoder.SlotCount;
+ double[] podValues = new double[slotCount];
+ for (ulong i = 0; i < slotCount; i++)
+ {
+ podValues[i] = 1.001 * i;
+ }
+
+ Console.Write("Running tests ");
+ for (int i = 0; i < count; i++)
+ {
+ /*
+ [Encoding]
+ For scale we use the square root of the last CoeffModulus prime
+ from parms.
+ */
+ double scale = Math.Sqrt(parms.CoeffModulus.Last().Value);
+ using Plaintext plain = new Plaintext(parms.PolyModulusDegree *
+ (ulong)parms.CoeffModulus.Count(), 0);
+ timeEncodeSum.Start();
+ ckksEncoder.Encode(podValues, scale, plain);
+ timeEncodeSum.Stop();
+
+ /*
+ [Decoding]
+ */
+ List podList = new List((int)slotCount);
+ timeDecodeSum.Start();
+ ckksEncoder.Decode(plain, podList);
+ timeDecodeSum.Stop();
+
+ /*
+ [Encryption]
+ */
+ using Ciphertext encrypted = new Ciphertext(context);
+ timeEncryptSum.Start();
+ encryptor.Encrypt(plain, encrypted);
+ timeEncryptSum.Stop();
+
+ /*
+ [Decryption]
+ */
+ using Plaintext plain2 = new Plaintext(polyModulusDegree, 0);
+ timeDecryptSum.Start();
+ decryptor.Decrypt(encrypted, plain2);
+ timeDecryptSum.Stop();
+
+ /*
+ [Add]
+ */
+ using Ciphertext encrypted1 = new Ciphertext(context);
+ ckksEncoder.Encode(i + 1, plain);
+ encryptor.Encrypt(plain, encrypted1);
+ using Ciphertext encrypted2 = new Ciphertext(context);
+ ckksEncoder.Encode(i + 1, plain2);
+ encryptor.Encrypt(plain2, encrypted2);
+ timeAddSum.Start();
+ evaluator.AddInplace(encrypted1, encrypted2);
+ evaluator.AddInplace(encrypted2, encrypted2);
+ evaluator.AddInplace(encrypted1, encrypted2);
+ timeAddSum.Stop();
+
+ /*
+ [Multiply]
+ */
+ encrypted1.Reserve(3);
+ timeMultiplySum.Start();
+ evaluator.MultiplyInplace(encrypted1, encrypted2);
+ timeMultiplySum.Stop();
+
+ /*
+ [Multiply Plain]
+ */
+ timeMultiplyPlainSum.Start();
+ evaluator.MultiplyPlainInplace(encrypted2, plain);
+ timeMultiplyPlainSum.Stop();
+
+ /*
+ [Square]
+ */
+ timeSquareSum.Start();
+ evaluator.SquareInplace(encrypted2);
+ timeSquareSum.Stop();
+
+ if (context.UsingKeyswitching)
+ {
+ /*
+ [Relinearize]
+ */
+ timeRelinearizeSum.Start();
+ evaluator.RelinearizeInplace(encrypted1, relinKeys);
+ timeRelinearizeSum.Stop();
+
+ /*
+ [Rescale]
+ */
+ timeRescaleSum.Start();
+ evaluator.RescaleToNextInplace(encrypted1);
+ timeRescaleSum.Stop();
+
+ /*
+ [Rotate Vector]
+ */
+ timeRotateOneStepSum.Start();
+ evaluator.RotateVectorInplace(encrypted, 1, galKeys);
+ evaluator.RotateVectorInplace(encrypted, -1, galKeys);
+ timeRotateOneStepSum.Stop();
+
+ /*
+ [Rotate Vector Random]
+ */
+ int randomRotation = rnd.Next() % (int)ckksEncoder.SlotCount;
+ timeRotateRandomSum.Start();
+ evaluator.RotateVectorInplace(encrypted, randomRotation, galKeys);
+ timeRotateRandomSum.Stop();
+
+ /*
+ [Complex Conjugate]
+ */
+ timeConjugateSum.Start();
+ evaluator.ComplexConjugateInplace(encrypted, galKeys);
+ timeConjugateSum.Stop();
+ }
+
+ /*
+ Print a dot to indicate progress.
+ */
+ Console.Write(".");
+ Console.Out.Flush();
+ }
+
+ Console.WriteLine(" Done");
+ Console.WriteLine();
+ Console.Out.Flush();
+
+ int avgEncode = (int)(timeEncodeSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgDecode = (int)(timeDecodeSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgEncrypt = (int)(timeEncryptSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgDecrypt = (int)(timeDecryptSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgAdd = (int)(timeAddSum.Elapsed.TotalMilliseconds * 1000 / (3 * count));
+ int avgMultiply = (int)(timeMultiplySum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgMultiplyPlain = (int)(timeMultiplyPlainSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgSquare = (int)(timeSquareSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgRelinearize = (int)(timeRelinearizeSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgRescale = (int)(timeRescaleSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgRotateOneStep = (int)(timeRotateOneStepSum.Elapsed.TotalMilliseconds * 1000 / (2 * count));
+ int avgRotateRandom = (int)(timeRotateRandomSum.Elapsed.TotalMilliseconds * 1000 / count);
+ int avgConjugate = (int)(timeConjugateSum.Elapsed.TotalMilliseconds * 1000 / count);
+
+ Console.WriteLine($"Average encode: {avgEncode} microseconds");
+ Console.WriteLine($"Average decode: {avgDecode} microseconds");
+ Console.WriteLine($"Average encrypt: {avgEncrypt} microseconds");
+ Console.WriteLine($"Average decrypt: {avgDecrypt} microseconds");
+ Console.WriteLine($"Average add: {avgAdd} microseconds");
+ Console.WriteLine($"Average multiply: {avgMultiply} microseconds");
+ Console.WriteLine($"Average multiply plain: {avgMultiplyPlain} microseconds");
+ Console.WriteLine($"Average square: {avgSquare} microseconds");
+ if (context.UsingKeyswitching)
+ {
+ Console.WriteLine($"Average relinearize: {avgRelinearize} microseconds");
+ Console.WriteLine($"Average rescale: {avgRescale} microseconds");
+ Console.WriteLine($"Average rotate vector one step: {avgRotateOneStep} microseconds");
+ Console.WriteLine($"Average rotate vector random: {avgRotateRandom} microseconds");
+ Console.WriteLine($"Average complex conjugate: {avgConjugate} microseconds");
+ }
+ Console.Out.Flush();
+ }
+
+ private static void ExampleBFVPerformanceDefault()
+ {
+ Utilities.PrintExampleBanner("BFV Performance Test with Degrees: 4096, 8192, and 16384");
+
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+ ulong polyModulusDegree = 4096;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ parms.PlainModulus = new Modulus(786433);
+ using (SEALContext context = new SEALContext(parms))
+ {
+ BFVPerformanceTest(context);
+ }
+
+ Console.WriteLine();
+ polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ parms.PlainModulus = new Modulus(786433);
+ using (SEALContext context = new SEALContext(parms))
+ {
+ BFVPerformanceTest(context);
+ }
+
+ Console.WriteLine();
+ polyModulusDegree = 16384;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ parms.PlainModulus = new Modulus(786433);
+ using (SEALContext context = new SEALContext(parms))
+ {
+ BFVPerformanceTest(context);
+ }
+
+ /*
+ Comment out the following to run the biggest example.
+ */
+ //Console.WriteLine();
+ //polyModulusDegree = 32768;
+ //parms.PolyModulusDegree = polyModulusDegree;
+ //parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ //parms.PlainModulus = new Modulus(786433);
+ //using (SEALContext context = new SEALContext(parms))
+ //{
+ // BFVPerformanceTest(context);
+ //}
+ }
+
+ private static void ExampleBFVPerformanceCustom()
+ {
+ Console.Write("> Set PolyModulusDegree (1024, 2048, 4096, 8192, 16384, or 32768): ");
+ string input = Console.ReadLine();
+ if (!ulong.TryParse(input, out ulong polyModulusDegree))
+ {
+ Console.WriteLine("Invalid option.");
+ return;
+ }
+ if (polyModulusDegree < 1024 || polyModulusDegree > 32768 ||
+ (polyModulusDegree & (polyModulusDegree - 1)) != 0)
+ {
+ Console.WriteLine("Invalid option.");
+ return;
+ }
+
+ string banner = $"BFV Performance Test with Degree: {polyModulusDegree}";
+ Utilities.PrintExampleBanner(banner);
+
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
+ {
+ PolyModulusDegree = polyModulusDegree,
+ CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree)
+ };
+ if (polyModulusDegree == 1024)
+ {
+ parms.PlainModulus = new Modulus(12289);
+ }
+ else
+ {
+ parms.PlainModulus = new Modulus(786433);
+ }
+
+ using (SEALContext context = new SEALContext(parms))
+ {
+ BFVPerformanceTest(context);
+ }
+ }
+
+ private static void ExampleCKKSPerformanceDefault()
+ {
+ Utilities.PrintExampleBanner("CKKS Performance Test with Degrees: 4096, 8192, and 16384");
+
+ // It is not recommended to use BFVDefault primes in CKKS. However, for performance
+ // test, BFVDefault primes are good enough.
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+ ulong polyModulusDegree = 4096;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ using (SEALContext context = new SEALContext(parms))
+ {
+ CKKSPerformanceTest(context);
+ }
+
+ Console.WriteLine();
+ polyModulusDegree = 8192;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ using (SEALContext context = new SEALContext(parms))
+ {
+ CKKSPerformanceTest(context);
+ }
+
+ Console.WriteLine();
+ polyModulusDegree = 16384;
+ parms.PolyModulusDegree = polyModulusDegree;
+ parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ using (SEALContext context = new SEALContext(parms))
+ {
+ CKKSPerformanceTest(context);
+ }
+
+ /*
+ Comment out the following to run the biggest example.
+ */
+ //Console.WriteLine();
+ //polyModulusDegree = 32768;
+ //parms.PolyModulusDegree = polyModulusDegree;
+ //parms.CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree);
+ //using (SEALContext context = new SEALContext(parms))
+ //{
+ // CKKSPerformanceTest(context);
+ //}
+ }
+
+ private static void ExampleCKKSPerformanceCustom()
+ {
+ Console.Write("> Set PolyModulusDegree (1024, 2048, 4096, 8192, 16384, or 32768): ");
+ string input = Console.ReadLine();
+ if (!ulong.TryParse(input, out ulong polyModulusDegree))
+ {
+ Console.WriteLine("Invalid option.");
+ return;
+ }
+ if (polyModulusDegree < 1024 || polyModulusDegree > 32768 ||
+ (polyModulusDegree & (polyModulusDegree - 1)) != 0)
+ {
+ Console.WriteLine("Invalid option.");
+ return;
+ }
+
+ string banner = $"CKKS Performance Test with Degree: {polyModulusDegree}";
+ Utilities.PrintExampleBanner(banner);
+
+ using EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
+ {
+ PolyModulusDegree = polyModulusDegree,
+ CoeffModulus = CoeffModulus.BFVDefault(polyModulusDegree)
+ };
+
+ using (SEALContext context = new SEALContext(parms))
+ {
+ CKKSPerformanceTest(context);
+ }
+ }
+
+ private static void ExamplePerformanceTest()
+ {
+ Utilities.PrintExampleBanner("Example: Performance Test");
+
+ if (!Stopwatch.IsHighResolution)
+ {
+ Console.WriteLine("WARNING: High resolution stopwatch not available in this machine.");
+ Console.WriteLine(" Timings might not be accurate.");
+ }
+
+ while (true)
+ {
+ Console.WriteLine();
+ Console.WriteLine("Select a scheme (and optionally PolyModulusDegree):");
+ Console.WriteLine(" 1. BFV with default degrees");
+ Console.WriteLine(" 2. BFV with a custom degree");
+ Console.WriteLine(" 3. CKKS with default degrees");
+ Console.WriteLine(" 4. CKKS with a custom degree");
+ Console.WriteLine(" 0. Back to main menu");
+ Console.WriteLine();
+
+ ConsoleKeyInfo key;
+ do
+ {
+ Console.Write("> Run performance test (1 ~ 4) or go back (0): ");
+ key = Console.ReadKey();
+ Console.WriteLine();
+ } while (key.KeyChar < '0' || key.KeyChar > '4');
+ switch (key.Key)
+ {
+ case ConsoleKey.D1:
+ ExampleBFVPerformanceDefault();
+ break;
+
+ case ConsoleKey.D2:
+ ExampleBFVPerformanceCustom();
+ break;
+
+ case ConsoleKey.D3:
+ ExampleCKKSPerformanceDefault();
+ break;
+
+ case ConsoleKey.D4:
+ ExampleCKKSPerformanceCustom();
+ break;
+
+ case ConsoleKey.D0:
+ Console.WriteLine();
+ return;
+
+ default:
+ Console.WriteLine(" [Beep~~] Invalid option: type 0 ~ 4");
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/Examples.cs b/bigpiseal3.5.1/dotnet/examples/Examples.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f3690c3bac9375c1c9b39557d0baae3b202ec405
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/Examples.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL;
+using System;
+
+namespace SEALNetExamples
+{
+ partial class Examples
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Microsoft SEAL version: " + SEALVersion.Version);
+ while (true)
+ {
+ Console.WriteLine("+---------------------------------------------------------+");
+ Console.WriteLine("| The following examples should be executed while reading |");
+ Console.WriteLine("| comments in associated files in dotnet/examples/. |");
+ Console.WriteLine("+---------------------------------------------------------+");
+ Console.WriteLine("| Examples | Source Files |");
+ Console.WriteLine("+----------------------------+----------------------------+");
+ Console.WriteLine("| 1. BFV Basics | 1_BFV_Basics.cs |");
+ Console.WriteLine("| 2. Encoders | 2_Encoders.cs |");
+ Console.WriteLine("| 3. Levels | 3_Levels.cs |");
+ Console.WriteLine("| 4. CKKS Basics | 4_CKKS_Basics.cs |");
+ Console.WriteLine("| 5. Rotation | 5_Rotation.cs |");
+ Console.WriteLine("| 6. Serialization | 6_Serialization.cs |");
+ Console.WriteLine("| 7. Performance Test | 7_Performance.cs |");
+ Console.WriteLine("+----------------------------+----------------------------+");
+
+ /*
+ Print how much memory we have allocated from the current memory pool.
+ By default the memory pool will be a static global pool and the
+ MemoryManager class can be used to change it. Most users should have
+ little or no reason to touch the memory allocation system.
+ */
+ ulong megabytes = MemoryManager.GetPool().AllocByteCount >> 20;
+ Console.WriteLine("[{0,7} MB] Total allocation from the memory pool", megabytes);
+
+ ConsoleKeyInfo key;
+ do
+ {
+ Console.WriteLine();
+ Console.Write("> Run example (1 ~ 7) or exit (0): ");
+ key = Console.ReadKey();
+ Console.WriteLine();
+ } while (key.KeyChar < '0' || key.KeyChar > '7');
+ switch (key.Key)
+ {
+ case ConsoleKey.D1:
+ ExampleBFVBasics();
+ break;
+
+ case ConsoleKey.D2:
+ ExampleEncoders();
+ break;
+
+ case ConsoleKey.D3:
+ ExampleLevels();
+ break;
+
+ case ConsoleKey.D4:
+ ExampleCKKSBasics();
+ break;
+
+ case ConsoleKey.D5:
+ ExampleRotation();
+ break;
+
+ case ConsoleKey.D6:
+ ExampleSerialization();
+ break;
+
+ case ConsoleKey.D7:
+ ExamplePerformanceTest();
+ break;
+
+ case ConsoleKey.D0:
+ return;
+
+ default:
+ Console.WriteLine(" [Beep~~] Invalid option: type 0 ~ 7");
+ break;
+ }
+
+ /*
+ We may want to force a garbage collection after each example to accurately show memory pool use.
+ */
+ GC.Collect();
+ }
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/examples/SEALNetExamples.csproj b/bigpiseal3.5.1/dotnet/examples/SEALNetExamples.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..73063c88fba67f34677b79a4830edf998e0f6e96
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/SEALNetExamples.csproj
@@ -0,0 +1,31 @@
+
+
+
+ Exe
+ netcoreapp3.1
+ Microsoft Research
+ Microsoft Corporation
+ .NET wrapper examples for Microsoft SEAL
+ Microsoft Corporation 2020
+
+
+
+ x64
+ $(ProjectDir)../../bin/dotnet/$(Configuration)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bigpiseal3.5.1/dotnet/examples/Utilities.cs b/bigpiseal3.5.1/dotnet/examples/Utilities.cs
new file mode 100644
index 0000000000000000000000000000000000000000..63f8511b14dd6258d6c4d1517ac22d2c0ab0cc77
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/examples/Utilities.cs
@@ -0,0 +1,189 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace SEALNetExamples
+{
+ public static class Utilities
+ {
+ ///
+ /// Helper function: Prints the name of the example in a fancy banner.
+ ///
+ public static void PrintExampleBanner(string title)
+ {
+ if (!string.IsNullOrEmpty(title))
+ {
+ int titleLength = title.Length;
+ int bannerLength = titleLength + 2 * 10;
+ string bannerTop = "+" + new string('-', bannerLength - 2) + "+";
+ string bannerMiddle =
+ "|" + new string(' ', 9) + title + new string(' ', 9) + "|";
+
+ Console.WriteLine();
+ Console.WriteLine(bannerTop);
+ Console.WriteLine(bannerMiddle);
+ Console.WriteLine(bannerTop);
+ }
+ }
+
+ ///
+ /// Helper function: Prints the parameters in a SEALContext.
+ ///
+ public static void PrintParameters(SEALContext context)
+ {
+ // Verify parameters
+ if (null == context)
+ {
+ throw new ArgumentNullException("context is not set");
+ }
+ SEALContext.ContextData contextData = context.KeyContextData;
+
+ /*
+ Which scheme are we using?
+ */
+ string schemeName = null;
+ switch (contextData.Parms.Scheme)
+ {
+ case SchemeType.BFV:
+ schemeName = "BFV";
+ break;
+ case SchemeType.CKKS:
+ schemeName = "CKKS";
+ break;
+ default:
+ throw new ArgumentException("unsupported scheme");
+ }
+
+ Console.WriteLine("/");
+ Console.WriteLine("| Encryption parameters:");
+ Console.WriteLine($"| Scheme: {schemeName}");
+ Console.WriteLine("| PolyModulusDegree: {0}",
+ contextData.Parms.PolyModulusDegree);
+
+ /*
+ Print the size of the true (product) coefficient modulus.
+ */
+ Console.Write("| CoeffModulus size: {0} (",
+ contextData.TotalCoeffModulusBitCount);
+ List coeffModulus =
+ (List)contextData.Parms.CoeffModulus;
+ for (int i = 0; i < coeffModulus.Count - 1; i++)
+ {
+ Console.Write($"{coeffModulus[i].BitCount} + ");
+ }
+ Console.WriteLine($"{coeffModulus.Last().BitCount}) bits");
+
+ /*
+ For the BFV scheme print the PlainModulus parameter.
+ */
+ if (contextData.Parms.Scheme == SchemeType.BFV)
+ {
+ Console.WriteLine("| PlainModulus: {0}",
+ contextData.Parms.PlainModulus.Value);
+ }
+
+ Console.WriteLine("\\");
+ }
+
+ ///
+ /// Helper function: Print the first and last printSize elements
+ /// of a 2 row matrix.
+ ///
+ public static void PrintMatrix(IEnumerable matrixPar,
+ int rowSize, int printSize = 5)
+ {
+ ulong[] matrix = matrixPar.ToArray();
+ Console.WriteLine();
+
+ /*
+ We're not going to print every column of the matrix (may be big). Instead
+ print printSize slots from beginning and end of the matrix.
+ */
+ Console.Write(" [");
+ for (int i = 0; i < printSize; i++)
+ {
+ Console.Write("{0,3}, ", matrix[i]);
+ }
+ Console.Write(" ...");
+ for (int i = rowSize - printSize; i < rowSize; i++)
+ {
+ Console.Write(", {0,3}", matrix[i]);
+ }
+ Console.WriteLine(" ]");
+ Console.Write(" [");
+ for (int i = rowSize; i < rowSize + printSize; i++)
+ {
+ Console.Write("{0,3}, ", matrix[i]);
+ }
+ Console.Write(" ...");
+ for (int i = 2 * rowSize - printSize; i < 2 * rowSize; i++)
+ {
+ Console.Write(", {0,3}", matrix[i]);
+ }
+ Console.WriteLine(" ]");
+ Console.WriteLine();
+ }
+
+ ///
+ /// Helper function: Convert a ulong to a hex string representation
+ ///
+ public static string ULongToString(ulong value)
+ {
+ byte[] bytes = BitConverter.GetBytes(value);
+ return BitConverter.ToString(bytes).Replace("-", "");
+ }
+
+ ///
+ /// Helper function: Prints a vector of floating-point values.
+ ///
+ public static void PrintVector(
+ IEnumerable vec, int printSize = 4, int prec = 3)
+ {
+ string numFormat = string.Format("{{0:N{0}}}", prec);
+ T[] veca = vec.ToArray();
+ int slotCount = veca.Length;
+ Console.WriteLine();
+ if (slotCount <= 2 * printSize)
+ {
+ Console.Write(" [");
+ for (int i = 0; i < slotCount; i++)
+ {
+ Console.Write(" " + string.Format(numFormat, veca[i]));
+ if (i != (slotCount - 1))
+ Console.Write(",");
+ else
+ Console.Write(" ]");
+ }
+ Console.WriteLine();
+ }
+ else
+ {
+ Console.Write(" [");
+ for (int i = 0; i < printSize; i++)
+ {
+ Console.Write(" "+ string.Format(numFormat, veca[i]) + ", ");
+ }
+ if (veca.Length > 2 * printSize)
+ {
+ Console.Write(" ...");
+ }
+ for (int i = slotCount - printSize; i < slotCount; i++)
+ {
+ Console.Write(", " + string.Format(numFormat, veca[i]));
+ }
+ Console.WriteLine(" ]");
+ }
+ Console.WriteLine();
+ }
+
+ public static void PrintLine([CallerLineNumber] int lineNumber = 0)
+ {
+ Console.Write("Line {0,3} --> ", lineNumber);
+ }
+ }
+}
\ No newline at end of file
diff --git a/bigpiseal3.5.1/dotnet/nuget/NUGET.md b/bigpiseal3.5.1/dotnet/nuget/NUGET.md
new file mode 100644
index 0000000000000000000000000000000000000000..8a7315be4dae3dd20f917f8492f47f16e7f8e72a
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/nuget/NUGET.md
@@ -0,0 +1,36 @@
+# Creating a NuGet package
+
+After building `dotnet\src\SEALNet.csproj` you can create a NuGet package that you can
+use to easily add Microsoft SEAL capabilities to all of your .NET projects. Currently
+the NuGet package is only supported in Windows.
+
+You will need to:
+1. Compile binaries
+ 1. `native\src\SEAL.vcxproj`
+ 2. `native\src\SEAL_C.vcxproj`
+ 3. `dotnet\src\SEALNet.csproj`
+3. [Download the NuGet command line tool](https://dist.nuget.org/win-x86-commandline/latest/nuget.exe)
+4. Run the command below to create NuGet package
+5. Add NuGet package reference to your .NET projects
+
+The command to create the NuGet package after compiling binaries is the following:
+
+````
+cd dotnet\nuget
+nuget.exe pack SEALNet.nuspec -properties Configuration=Release -Verbosity detailed -OutputDir Release
+cd ..\..
+````
+
+After the package is created, copy it from `dotnet\nuget\Release` to a known location (e.g., `C:\NuGetPackages`).
+
+To add a reference to the NuGet package, you will need to configure Visual Studio so it can find
+packages in this known location. In Microsoft Visual Studio 2019, for example, you can:
+1. Select the menu uption `Tools / Options...`
+2. On the left pane of the Options dialog, navigate to `NuGet Package Manager / Package Sources`
+3. On the right pane of the Options dialog, add a new package source that points to the directory
+ where you copied the NuGet package (e.g., `C:\NuGetPackages`)
+
+After this, you should be able to add a reference to this package in your own .NET project. After
+creating or opening your project in Visual Studio, you can right click on the project in the
+Solution Explorer window, and select `Manage NuGet packages...`. In the window that appears
+you will be able to select the `Microsoft.Research.SEAL` NuGet package to add to your project.
\ No newline at end of file
diff --git a/bigpiseal3.5.1/dotnet/nuget/SEALNet-multi.nuspec.in b/bigpiseal3.5.1/dotnet/nuget/SEALNet-multi.nuspec.in
new file mode 100644
index 0000000000000000000000000000000000000000..6f77d3624582d9e86df6dc74fb6fdf5cce7e491c
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/nuget/SEALNet-multi.nuspec.in
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+ Microsoft.Research.SEALNet
+ @SEAL_VERSION@
+ Microsoft SEAL
+ Microsoft
+ Microsoft
+ http://sealcrypto.org
+ LICENSE
+ false
+ Microsoft SEAL is an easy-to-use and powerful open source homomorphic encryption library, developed by researchers in the Cryptography and Privacy Research Group at Microsoft Research. Microsoft SEAL is licensed under the MIT license.
+ https://GitHub.com/Microsoft/SEAL
+ © Microsoft Corporation. All rights reserved.
+ c# crypto cryptography homomorphic encryption
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bigpiseal3.5.1/dotnet/nuget/SEALNet.nuspec.in b/bigpiseal3.5.1/dotnet/nuget/SEALNet.nuspec.in
new file mode 100644
index 0000000000000000000000000000000000000000..5fd8c2154df3b3fc476faebb7cb8446d31b334f2
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/nuget/SEALNet.nuspec.in
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ Microsoft.Research.SEALNet
+ @SEAL_VERSION@
+ Microsoft SEAL
+ Microsoft
+ Microsoft
+ http://sealcrypto.org
+ LICENSE
+ false
+ Microsoft SEAL is an easy-to-use and powerful open source homomorphic encryption library, developed by researchers in the Cryptography and Privacy Research Group at Microsoft Research. Microsoft SEAL is licensed under the MIT license.
+ https://GitHub.com/Microsoft/SEAL
+ © Microsoft Corporation. All rights reserved.
+ c# crypto cryptography homomorphic encryption
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bigpiseal3.5.1/dotnet/nuget/SEALNet.targets.in b/bigpiseal3.5.1/dotnet/nuget/SEALNet.targets.in
new file mode 100644
index 0000000000000000000000000000000000000000..a0071eb8c3547738a0a63d5f530dae91531a1b5b
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/nuget/SEALNet.targets.in
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ sealc.dll
+ libsealc.so
+ libsealc.dylib
+ PreserveNewest
+
+
+
+
+ arm64-v8a
+ libs\arm64-v8a\libsealc.so
+
+
+ x86_64
+ libs\x86_64\libsealc.so
+
+
+
diff --git a/bigpiseal3.5.1/dotnet/src/BatchEncoder.cs b/bigpiseal3.5.1/dotnet/src/BatchEncoder.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e623a7a12660ca086c16713dd5413fa459f8b811
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/BatchEncoder.cs
@@ -0,0 +1,276 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Provides functionality for CRT batching. If the polynomial modulus degree is N, and
+ /// the plaintext modulus is a prime number T such that T is congruent to 1 modulo 2N,
+ /// then BatchEncoder allows the plaintext elements to be viewed as 2-by-(N/2)
+ /// matrices of integers modulo T. Homomorphic operations performed on such encrypted
+ /// matrices are applied coefficient (slot) wise, enabling powerful SIMD functionality
+ /// for computations that are vectorizable. This functionality is often called "batching"
+ /// in the homomorphic encryption literature.
+ ///
+ ///
+ ///
+ /// Mathematical Background
+ /// Mathematically speaking, if the polynomial modulus is X^N+1, N is a power of two, and
+ /// PlainModulus is a prime number T such that 2N divides T-1, then integers modulo T
+ /// contain a primitive 2N-th root of unity and the polynomial X^N+1 splits into n distinct
+ /// linear factors as X^N+1 = (X-a_1)*...*(X-a_N) mod T, where the constants a_1, ..., a_n
+ /// are all the distinct primitive 2N-th roots of unity in integers modulo T. The Chinese
+ /// Remainder Theorem (CRT) states that the plaintext space Z_T[X]/(X^N+1) in this case is
+ /// isomorphic (as an algebra) to the N-fold direct product of fields Z_T. The isomorphism
+ /// is easy to compute explicitly in both directions, which is what this class does.
+ /// Furthermore, the Galois group of the extension is (Z/2NZ)* ~= Z/2Z x Z/(N/2) whose
+ /// action on the primitive roots of unity is easy to describe. Since the batching slots
+ /// correspond 1-to-1 to the primitive roots of unity, applying Galois automorphisms on the
+ /// plaintext act by permuting the slots. By applying generators of the two cyclic
+ /// subgroups of the Galois group, we can effectively view the plaintext as a 2-by-(N/2)
+ /// matrix, and enable cyclic row rotations, and column rotations (row swaps).
+ ///
+ ///
+ /// Valid Parameters
+ /// Whether batching can be used depends on whether the plaintext modulus has been chosen
+ /// appropriately. Thus, to construct a BatchEncoder the user must provide an instance
+ /// of SEALContext such that its associated EncryptionParameterQualifiers object has the
+ /// flags ParametersSet and EnableBatching set to true.
+ ///
+ ///
+ /// see EncryptionParameters for more information about encryption parameters.
+ /// see EncryptionParameterQualifiers for more information about parameter qualifiers.
+ /// see Evaluator for rotating rows and columns of encrypted matrices.
+ public class BatchEncoder : NativeObject
+ {
+ ///
+ /// Creates a BatchEncoder. It is necessary that the encryption parameters
+ /// given through the SEALContext object support batching.
+ ///
+ /// The SEALContext
+ /// @param[in] context
+ /// if context is null.
+ /// if the context is not set or encryption
+ /// parameters are not valid for batching
+ /// if scheme is not SchemeType.BFV
+ public BatchEncoder(SEALContext context)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+
+ SEALContext.ContextData contextData = context.FirstContextData;
+ if (contextData.Parms.Scheme != SchemeType.BFV)
+ throw new ArgumentException("Unsupported scheme");
+ if (!contextData.Qualifiers.UsingBatching)
+ throw new ArgumentException("Encryption parameters are not valid for batching");
+
+ NativeMethods.BatchEncoder_Create(context.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a plaintext from a given matrix. This function "batches" a given matrix
+ /// of integers modulo the plaintext modulus into a plaintext element, and stores
+ /// the result in the destination parameter. The input vector must have size at most equal
+ /// to the degree of the polynomial modulus. The first half of the elements represent the
+ /// first row of the matrix, and the second half represent the second row. The numbers
+ /// in the matrix can be at most equal to the plaintext modulus for it to represent
+ /// a valid plaintext.
+ ///
+ /// If the destination plaintext overlaps the input values in memory, the behavior of
+ /// this function is undefined.
+ ///
+ /// The matrix of integers modulo plaintext modulus to batch
+ /// The plaintext polynomial to overwrite with the result
+ /// if either values or destination are null
+ /// if values is too large
+ public void Encode(IEnumerable values, Plaintext destination)
+ {
+ if (null == values)
+ throw new ArgumentNullException(nameof(values));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ ulong[] valarray = values.ToArray();
+ NativeMethods.BatchEncoder_Encode(NativePtr, (ulong)valarray.LongLength, valarray, destination.NativePtr);
+ }
+
+ ///
+ /// Creates a plaintext from a given matrix. This function "batches" a given matrix
+ /// of integers modulo the plaintext modulus into a plaintext element, and stores
+ /// the result in the destination parameter. The input vector must have size at most equal
+ /// to the degree of the polynomial modulus. The first half of the elements represent the
+ /// first row of the matrix, and the second half represent the second row. The numbers
+ /// in the matrix can be at most equal to the plaintext modulus for it to represent
+ /// a valid plaintext.
+ ///
+ /// If the destination plaintext overlaps the input values in memory, the behavior of
+ /// this function is undefined.
+ ///
+ /// The matrix of integers modulo plaintext modulus to batch
+ /// The plaintext polynomial to overwrite with the result
+ /// if either values or destionation are null
+ /// if values is too large
+ public void Encode(IEnumerable values, Plaintext destination)
+ {
+ if (null == values)
+ throw new ArgumentNullException(nameof(values));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ long[] valarray = values.ToArray();
+ NativeMethods.BatchEncoder_Encode(NativePtr, (ulong)valarray.LongLength, valarray, destination.NativePtr);
+ }
+
+ ///
+ /// Creates a plaintext from a given matrix. This function "batches" a given matrix
+ /// of integers modulo the plaintext modulus in-place into a plaintext ready to be
+ /// encrypted. The matrix is given as a plaintext element whose first N/2 coefficients
+ /// represent the first row of the matrix, and the second N/2 coefficients represent the
+ /// second row, where N denotes the degree of the polynomial modulus. The input plaintext
+ /// must have degress less than the polynomial modulus, and coefficients less than the
+ /// plaintext modulus, i.e. it must be a valid plaintext for the encryption parameters.
+ /// Dynamic memory allocations in the process are allocated from the memory pool pointed
+ /// to by the given MemoryPoolHandle.
+ ///
+ /// The matrix of integers modulo plaintext modulus to batch
+ ///
+ /// if plain is null.
+ /// if plain is not valid for the encryption parameters
+ /// if plain is in NTT form
+ /// if pool is uninitialized
+ public void Encode(Plaintext plain, MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.BatchEncoder_Encode(NativePtr, plain.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Inverse of encode. This function "unbatches" a given plaintext into a matrix
+ /// of integers modulo the plaintext modulus, and stores the result in the destination
+ /// parameter. The input plaintext must have degress less than the polynomial modulus,
+ /// and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext
+ /// for the encryption parameters. Dynamic memory allocations in the process are
+ /// allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The plaintext polynomial to unbatch
+ /// The matrix to be overwritten with the values in the slots
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain or destionation are null
+ /// if plain is not valid for the encryption parameters
+ /// if plain is in NTT form
+ /// if pool is uninitialized
+ public void Decode(Plaintext plain, ICollection destination, MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ ulong destCount = 0;
+
+ // Allocate a big enough array to hold the result
+ ulong[] destArray = new ulong[SlotCount];
+ NativeMethods.BatchEncoder_Decode(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr);
+
+ // Transfer result to actual destination
+ destination.Clear();
+ for (ulong i = 0; i < destCount; i++)
+ {
+ destination.Add(destArray[i]);
+ }
+ }
+
+ ///
+ /// Inverse of encode. This function "unbatches" a given plaintext into a matrix
+ /// of integers modulo the plaintext modulus, and stores the result in the destination
+ /// parameter. The input plaintext must have degress less than the polynomial modulus,
+ /// and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext
+ /// for the encryption parameters. Dynamic memory allocations in the process are
+ /// allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The plaintext polynomial to unbatch
+ /// The matrix to be overwritten with the values in the slots
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain or destination are null
+ /// if plain is not valid for the encryption parameters
+ /// if plain is in NTT form
+ /// if pool is uninitialized
+ public void Decode(Plaintext plain, ICollection destination, MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ ulong destCount = 0;
+
+ // Allocate a big enough array to hold the result
+ long[] destArray = new long[SlotCount];
+ NativeMethods.BatchEncoder_Decode(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr);
+
+ // Transfer result to actual destination
+ destination.Clear();
+ for (ulong i = 0; i < destCount; i++)
+ {
+ destination.Add(destArray[i]);
+ }
+ }
+
+ ///
+ /// Inverse of encode. This function "unbatches" a given plaintext in-place into
+ /// a matrix of integers modulo the plaintext modulus. The input plaintext must have
+ /// degress less than the polynomial modulus, and coefficients less than the plaintext
+ /// modulus, i.e. it must be a valid plaintext for the encryption parameters. Dynamic
+ /// memory allocations in the process are allocated from the memory pool pointed to by
+ /// the given MemoryPoolHandle.
+ ///
+ /// The plaintext polynomial to unbatch
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if plain is null
+ /// if plain is not valid for the encryption parameters
+ /// if plain is in NTT form
+ /// if pool is uninitialized
+ public void Decode(Plaintext plain, MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+
+ NativeMethods.BatchEncoder_Decode(NativePtr, plain.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Returns the number of slots.
+ ///
+ public ulong SlotCount
+ {
+ get
+ {
+ NativeMethods.BatchEncoder_GetSlotCount(NativePtr, out ulong slotCount);
+ return slotCount;
+ }
+ }
+
+ ///
+ /// Destroy native object
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.BatchEncoder_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/BigUInt.cs b/bigpiseal3.5.1/dotnet/src/BigUInt.cs
new file mode 100644
index 0000000000000000000000000000000000000000..67b8b1d8cb861ac28c2feac57ec557b30fe1306b
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/BigUInt.cs
@@ -0,0 +1,1348 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.IO;
+using System.Numerics;
+using System.Text;
+using Microsoft.Research.SEAL.Tools;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Represents an unsigned integer with a specified bit width.
+ ///
+ ///
+ ///
+ /// Represents an unsigned integer with a specified bit width. BigUInts are mutable
+ /// and able to be resized. The bit count for a BigUInt (which can be read with
+ /// ) is set initially by the constructor and can be resized
+ /// either explicitly with the function or implicitly
+ /// with an assignment operation (e.g., one of the Set() functions). A rich set
+ /// of unsigned integer operations are provided by the BigUInt class, including
+ /// comparison, traditional arithmetic (addition, subtraction, multiplication,
+ /// division), and modular arithmetic functions.
+ ///
+ ///
+ /// The backing array for a BigUInt stores its unsigned integer value as a contiguous
+ /// System.UInt64 array. Each System.UInt64 in the array sequentially represents
+ /// 64-bits of the integer value, with the least significant quad-word storing the
+ /// lower 64-bits and the order of the bits for each quad word dependent on the
+ /// architecture's System.UInt64 representation. The size of the array equals the bit
+ /// count of the BigUInt (which can be read with ) rounded up
+ /// to the next System.UInt64 boundary (i.e., rounded up to the next 64-bit boundary).
+ /// The property returns the number of System.UInt64 in the
+ /// backing array. The method returns an element of the
+ /// System.UInt64 array. Additionally, the index property allows accessing the
+ /// individual bytes of the integer value in a platform-independent way - for example,
+ /// reading the third byte will always return bits 16-24 of the BigUInt value
+ /// regardless of the platform being little-endian or big-endian.
+ ///
+ ///
+ /// Both the copy constructor and the Set function allocate more memory for the
+ /// backing array when needed, i.e. when the source BigUInt has a larger backing
+ /// array than the destination. Conversely, when the destination backing array is
+ /// already large enough, the data is only copied and the unnecessary higher order
+ /// bits are set to zero. When new memory has to be allocated, only the significant
+ /// bits of the source BigUInt are taken into account. This is is important, because
+ /// it avoids unnecessary zero bits to be included in the destination, which in some
+ /// cases could accumulate and result in very large unnecessary allocations. However,
+ /// sometimes it is necessary to preserve the original size, even if some of the
+ /// leading bits are zero. For this purpose BigUInt contains functions
+ /// and , which create an exact
+ /// copy of the source BigUInt.
+ ///
+ ///
+ /// An aliased BigUInt (which can be determined with ) is
+ /// a special type of BigUInt that does not manage its underlying System.UInt64
+ /// pointer used to store the value. An aliased BigUInt supports most of the same
+ /// operations as a non-aliased BigUInt, including reading and writing the value,
+ /// however an aliased BigUInt does not internally allocate or deallocate its backing
+ /// array and, therefore, does not support resizing. Any attempt, either explicitly
+ /// or implicitly, to resize the BigUInt will result in an exception being thrown.
+ /// Aliased BigUInt's are only created internally. Aliasing is useful in cases where
+ /// it is desirable to not have each BigUInt manage its own memory allocation and/or
+ /// to prevent unnecessary copying.
+ ///
+ ///
+ /// In general, reading a BigUInt is thread-safe while mutating is not. Specifically,
+ /// the backing array may be freed whenever a resize occurs or the BigUInt is
+ /// destroyed. When it is known that a resize will not occur, concurrent reading and
+ /// mutating will not inherently fail but it is possible for a read to see a partially
+ /// updated value from a concurrent write. A non-aliased BigUInt allocates its backing
+ /// array from the global (thread-safe) memory pool. Consequently, creating or
+ /// resizing a large number of BigUInt can result in a performance loss due to thread
+ /// contention.
+ ///
+ ///
+ public class BigUInt : NativeObject, IEquatable, IComparable
+ {
+ /// Creates an empty BigUInt with zero bit width.
+ ///
+ /// Creates an empty BigUInt with zero bit width. No memory is allocated by
+ /// this constructor.
+ ///
+ public BigUInt()
+ {
+ IntPtr ptr = IntPtr.Zero;
+ NativeMethods.BigUInt_Create(out ptr);
+ NativePtr = ptr;
+ }
+
+ /// Creates a zero-initialized BigUInt of the specified bit
+ /// width.
+ /// The bit width
+ /// if bitCount is negative
+ public BigUInt(int bitCount)
+ {
+ if (bitCount < 0)
+ throw new ArgumentException("bitCount cannot be negative");
+
+ IntPtr ptr = IntPtr.Zero;
+ NativeMethods.BigUInt_Create(bitCount, out ptr);
+ NativePtr = ptr;
+ }
+
+ /// Creates a BigUInt of the specified bit width and initializes
+ /// it with the unsigned hexadecimal integer specified by the string.
+ ///
+ /// Creates a BigUInt of the specified bit width and initializes it with
+ /// the unsigned hexadecimal integer specified by the string. The string
+ /// must match the format returned by and must
+ /// consist of only the characters 0-9, A-F, or a-f, most-significant nibble
+ /// first.
+ ///
+ ///
+ /// The bit width
+ /// The hexadecimal integer string specifying the
+ /// initial value
+ /// if hexString is null
+ /// if bitCount is negative
+ /// if hexString does not adhere to the
+ /// expected format
+ public BigUInt(int bitCount, string hexString)
+ {
+ if (null == hexString)
+ throw new ArgumentNullException(nameof(hexString));
+ if (bitCount < 0)
+ throw new ArgumentException("bitCount cannot be negative");
+
+ IntPtr ptr = IntPtr.Zero;
+ NativeMethods.BigUInt_Create(bitCount, hexString, out ptr);
+ NativePtr = ptr;
+ }
+
+ /// Creates a BigUInt of the specified bit width and initializes it
+ /// to the specified unsigned integer value.
+ ///
+ /// The bit width
+ /// The initial value to set the BigUInt
+ /// if bitCount is negative
+ public BigUInt(int bitCount, ulong value)
+ {
+ if (bitCount < 0)
+ throw new ArgumentException("bitCount cannot be negative");
+
+ IntPtr ptr = IntPtr.Zero;
+ NativeMethods.BigUInt_Create(bitCount, value, out ptr);
+ NativePtr = ptr;
+ }
+
+ /// Creates a BigUInt initialized and minimally sized to fit the
+ /// unsigned hexadecimal integer specified by the string.
+ ///
+ /// Creates a BigUInt initialized and minimally sized to fit the unsigned
+ /// hexadecimal integer specified by the string. The string matches the format
+ /// returned by and must consist of only the characters
+ /// 0-9, A-F, or a-f, most-significant nibble first.
+ ///
+ /// The hexadecimal integer string specifying the
+ /// initial value
+ /// if hexString is null
+ /// if hexString does not adhere to the
+ /// expected format
+ public BigUInt(string hexString)
+ {
+ if (null == hexString)
+ throw new ArgumentNullException(nameof(hexString));
+
+ IntPtr ptr = IntPtr.Zero;
+ NativeMethods.BigUInt_Create(hexString, out ptr);
+ NativePtr = ptr;
+ }
+
+ /// Creates a deep copy of a BigUInt.
+ ///
+ /// Creates a deep copy of a BigUInt. The created BigUInt will have the same
+ /// bit count and value as the original.
+ ///
+ /// The BigUInt to copy from
+ /// if copy is null
+ public BigUInt(BigUInt copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ IntPtr ptr = IntPtr.Zero;
+ NativeMethods.BigUInt_Create(copy.NativePtr, out ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a BigUInt initialized and minimally sized to fit the unsigned
+ /// hexadecimal integer specified by the .
+ ///
+ /// The initial value of the BigUInt
+ /// if bigInteger is null
+ public BigUInt(BigInteger bigInteger)
+ {
+ if (null == bigInteger)
+ throw new ArgumentNullException(nameof(bigInteger));
+
+ string hex = bigInteger.ToString("X");
+ IntPtr ptr = IntPtr.Zero;
+ NativeMethods.BigUInt_Create(hex, out ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a BigUInt from an IntPtr.
+ ///
+ /// Native pointer
+ /// Whether this BigUInt instance owns the native
+ /// pointer
+ internal BigUInt(IntPtr ptr, bool owned = true)
+ : base(ptr, owned)
+ {
+ }
+
+ /// Returns whether or not the BigUInt is an alias.
+ public bool IsAlias
+ {
+ get
+ {
+ NativeMethods.BigUInt_IsAlias(NativePtr, out bool isAlias);
+ return isAlias;
+ }
+ }
+
+ /// Returns the bit count for the BigUInt.
+ public int BitCount
+ {
+ get
+ {
+ NativeMethods.BigUInt_BitCount(NativePtr, out int bitCount);
+ return bitCount;
+ }
+ }
+
+ /// Returns the number of bytes in the backing array used to store
+ /// the BigUInt value.
+ public ulong ByteCount
+ {
+ get
+ {
+ NativeMethods.BigUInt_ByteCount(NativePtr, out ulong byteCount);
+ return byteCount;
+ }
+ }
+
+ /// Returns the number of System.UInt64 in the backing array used
+ /// to store the BigUInt value.
+ public ulong UInt64Count
+ {
+ get
+ {
+ NativeMethods.BigUInt_UInt64Count(NativePtr, out ulong uint64Count);
+ return uint64Count;
+ }
+ }
+
+ /// Gets/sets the byte at the corresponding byte index of the BigUInt's
+ /// integer value.
+ ///
+ /// Gets/sets the byte at the corresponding byte index of the BigUInt's integer
+ /// value. The bytes of the BigUInt are indexed least-significant byte first.
+ ///
+ /// The index of the byte to get/set
+ /// if index is not within
+ /// [0, )
+ public byte this[ulong index]
+ {
+ get
+ {
+ if (index >= ByteCount)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
+ NativeMethods.BigUInt_Get(NativePtr, index, out byte result);
+ return result;
+ }
+ set
+ {
+ if (index >= ByteCount)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
+ NativeMethods.BigUInt_Set(NativePtr, index, value);
+ }
+ }
+
+ ///
+ /// Returns the ulong value at a given position in the backing array storing
+ /// the BigUInt value.
+ ///
+ ///
+ /// Returns the value that is at position
+ /// in the backing array storing the BigUInt value.
+ ///
+ ///
+ /// if index is not within
+ /// [0, )
+ public ulong Data(ulong index)
+ {
+ if (index >= UInt64Count)
+ throw new ArgumentOutOfRangeException(nameof(index));
+
+ NativeMethods.BigUInt_GetU64(NativePtr, index, out ulong result);
+ return result;
+ }
+
+ ///
+ /// Returns whether or not the BigUInt has the value zero.
+ ///
+ public bool IsZero
+ {
+ get
+ {
+ NativeMethods.BigUInt_IsZero(NativePtr, out bool isZero);
+ return isZero;
+ }
+ }
+
+ ///
+ /// Returns the number of significant bits for the BigUInt.
+ ///
+ public int GetSignificantBitCount()
+ {
+ NativeMethods.BigUInt_GetSignificantBitCount(NativePtr, out int result);
+ return result;
+ }
+
+ ///
+ /// Overwrites the BigUInt with the value of the specified BigUInt, enlarging
+ /// if needed to fit the assigned value.
+ ///
+ ///
+ /// Overwrites the BigUInt with the value of the specified BigUInt, enlarging
+ /// if needed to fit the assigned value. Only significant bits are used to size
+ /// the BigUInt.
+ ///
+ /// The BigUInt whose value should be assigned to the
+ /// current BigUInt
+ /// if assign is null
+ /// if BigUInt is an alias and
+ /// the assigned BigUInt is too large to fit the current bit width
+ public void Set(BigUInt assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+ if (IsAlias)
+ throw new InvalidOperationException("Cannot assign to an alias");
+
+ NativeMethods.BigUInt_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Overwrites the BigUInt with the unsigned hexadecimal value specified by
+ /// the string, enlarging if needed to fit the assigned value.
+ ///
+ ///
+ /// Overwrites the BigUInt with the unsigned hexadecimal value specified by
+ /// the string, enlarging if needed to fit the assigned value. The string must
+ /// match the format returned by and must consist of
+ /// only the characters 0-9, A-F, or a-f, most-significant nibble first.
+ ///
+ /// The hexadecimal integer string specifying the value
+ /// to assign
+ /// if assign is null
+ /// if assign does not adhere to the
+ /// expected format
+ /// if BigUInt is an alias and
+ /// the assigned value is too large to fit the current bit width
+ public void Set(string assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+ if (IsAlias)
+ throw new InvalidOperationException("Cannot assign to an alias");
+
+ NativeMethods.BigUInt_Set(NativePtr, assign);
+ }
+
+ /// Overwrites the BigUInt with the specified integer value, enlarging
+ /// if needed to fit the value.
+ ///
+ /// The value to assign
+ /// if BigUInt is an alias and
+ /// the significant bit count of assign is too large to fit the current bit
+ /// width
+ public void Set(ulong assign)
+ {
+ NativeMethods.BigUInt_Set(NativePtr, assign);
+ }
+
+ /// Sets the BigUInt value to zero.
+ ///
+ /// Sets the BigUInt value to zero. This does not resize the BigUInt.
+ ///
+ public void SetZero()
+ {
+ NativeMethods.BigUInt_SetZero(NativePtr);
+ }
+
+ ///
+ /// Returns an upper bound on the size of the BigUInt, as if it was written
+ /// to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.BigUInt_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the BigUInt to an output stream.
+ ///
+ /// Saves the BigUInt to an output stream. The full state of the BigUInt is
+ /// serialized, including insignificant bits. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the BigUInt to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.BigUInt_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ ///
+ /// Loads a BigUInt from an input stream overwriting the current BigUInt.
+ ///
+ /// The stream to load the BigUInt from
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, if the
+ /// loaded compression mode is not supported, or if the loaded BigUInt is too
+ /// large for an aliased BigUInt
+ public long Load(Stream stream)
+ {
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.BigUInt_Load(NativePtr, outptr, size, out outBytes),
+ stream);
+ }
+
+ ///
+ /// Resizes the BigUInt to the specified bit width, copying over the old
+ /// value as much as will fit.
+ ///
+ /// The bit width
+ /// if bitCount is negative
+ /// if the BigUInt is an
+ /// alias
+ public void Resize(int bitCount)
+ {
+ if (bitCount < 0)
+ throw new ArgumentException("bitCount cannot be negative");
+ if (IsAlias)
+ throw new InvalidOperationException("Cannot resize an alias");
+
+ NativeMethods.BigUInt_Resize(NativePtr, bitCount);
+ }
+
+ ///
+ /// Returns the BigUInt value as a .
+ ///
+ public BigInteger ToBigInteger()
+ {
+ ulong byteCount = ByteCount;
+ byte[] bytes = new byte[byteCount + 1];
+ for (ulong i = 0; i < byteCount; i++)
+ {
+ bytes[i] = this[i];
+ }
+ bytes[byteCount] = 0;
+
+ BigInteger result = new BigInteger(bytes);
+ return result;
+ }
+
+ ///
+ /// Returns the BigUInt value as a decimal string.
+ ///
+ public string ToDecimalString()
+ {
+ NativeMethods.BigUInt_ToDecimalString(NativePtr, null, length: out ulong length);
+ StringBuilder buffer = new StringBuilder(checked((int)length));
+ NativeMethods.BigUInt_ToDecimalString(NativePtr, buffer, out length);
+ return buffer.ToString();
+ }
+
+ ///
+ /// Compares a BigUInt and an unsigned integer and returns -1, 0, or 1 if
+ /// the BigUInt is less-than, equal-to, or greater-than the second operand
+ /// respectively. The input operands are not modified.
+ ///
+ /// The value to compare against
+ public int CompareTo(ulong compare)
+ {
+ NativeMethods.BigUInt_CompareTo(NativePtr, compare, out int result);
+ return result;
+ }
+
+ /// Divides two BigUInts and returns the quotient and sets the
+ /// remainder parameter to the remainder.
+ ///
+ /// Divides two BigUInts and returns the quotient and sets the remainder
+ /// parameter to the remainder. The bit count of the quotient is set to be
+ /// the significant bit count of the BigUInt. The remainder is resized if
+ /// and only if it is smaller than the bit count of the BigUInt.
+ ///
+ /// The second operand to divide
+ /// The BigUInt to store the remainder
+ /// if operand2 or remainder is
+ /// null
+ /// if operand2 is zero
+ /// if the remainder is an alias
+ /// and the operator attempts to enlarge the BigUInt to fit the result
+ public BigUInt DivideRemainder(BigUInt operand2, BigUInt remainder)
+ {
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+ if (null == remainder)
+ throw new ArgumentNullException(nameof(remainder));
+ if (operand2.IsZero)
+ throw new ArgumentException("operand2 is zero");
+ if (remainder.IsAlias)
+ throw new InvalidOperationException("remainder is an alias");
+
+ NativeMethods.BigUInt_DivideRemainder(NativePtr, operand2.NativePtr,
+ remainder.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Divides a BigUInt and an unsigned integer and returns the quotient
+ /// and sets the remainder parameter to the remainder.
+ ///
+ ///
+ /// Divides a BigUInt and an unsigned integer and returns the quotient and
+ /// sets the remainder parameter to the remainder. The bit count of the quotient
+ /// is set to be the significant bit count of the BigUInt. The remainder is
+ /// resized if and only if it is smaller than the bit count of the BigUInt.
+ ///
+ /// The second operand to divide
+ /// The BigUInt to store the remainder
+ /// if remainder is null
+ /// if operand2 is zero
+ /// if the remainder is an alias
+ /// which the function attempts to enlarge to fit the result
+ public BigUInt DivideRemainder(ulong operand2, BigUInt remainder)
+ {
+ if (null == remainder)
+ throw new ArgumentNullException(nameof(remainder));
+ if (operand2 == 0)
+ throw new ArgumentException("operand2 is zero");
+ if (remainder.IsAlias)
+ throw new InvalidOperationException("remainder is an alias");
+
+ NativeMethods.BigUInt_DivideRemainder(NativePtr, operand2,
+ remainder.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Returns the inverse of a BigUInt with respect to the specified
+ /// modulus.
+ ///
+ /// Returns the inverse of a BigUInt with respect to the specified modulus.
+ /// The original BigUInt is not modified. The bit count of the inverse is
+ /// set to be the significant bit count of the modulus.
+ ///
+ /// The modulus to calculate the inverse with respect
+ /// to
+ /// if modulus is null
+ /// if modulus is zero
+ /// if modulus is not greater than the
+ /// BigUInt value
+ /// if the BigUInt value and modulus
+ /// are not co-prime
+ /// if the BigUInt value is
+ /// zero
+ public BigUInt ModuloInvert(BigUInt modulus)
+ {
+ if (null == modulus)
+ throw new ArgumentNullException(nameof(modulus));
+
+ BigUInt result = null;
+ NativeMethods.BigUInt_ModuloInvert(NativePtr, modulus.NativePtr,
+ out IntPtr resultptr);
+ result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Returns the inverse of a BigUInt with respect to the specified
+ /// modulus.
+ ///
+ /// Returns the inverse of a BigUInt with respect to the specified modulus.
+ /// The original BigUInt is not modified. The bit count of the inverse is set
+ /// to be the significant bit count of the modulus.
+ ///
+ /// The modulus to calculate the inverse with respect
+ /// to
+ /// if modulus is zero
+ /// if modulus is not greater than the
+ /// BigUInt value
+ /// if the BigUInt value and modulus
+ /// are not co-prime
+ public BigUInt ModuloInvert(ulong modulus)
+ {
+ NativeMethods.BigUInt_ModuloInvert(NativePtr, modulus, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Attempts to calculate the inverse of a BigUInt with respect to
+ /// the specified modulus, returning whether or not the inverse was successful
+ /// and setting the inverse parameter to the inverse.
+ ///
+ /// Attempts to calculate the inverse of a BigUInt with respect to the specified
+ /// modulus, returning whether or not the inverse was successful and setting
+ /// the inverse parameter to the inverse. The original BigUInt is not modified.
+ /// The inverse parameter is resized if and only if its bit count is smaller
+ /// than the significant bit count of the modulus.
+ ///
+ /// The modulus to calculate the inverse with respect
+ /// to
+ /// Stores the inverse if the inverse operation was
+ /// successful
+ /// if modulus or inverse is null
+ /// if modulus is zero
+ /// if modulus is not greater than the
+ /// BigUInt value
+ /// if the inverse is an alias
+ /// which the function attempts to enlarge to fit the result
+ public bool TryModuloInvert(BigUInt modulus, BigUInt inverse)
+ {
+ if (null == modulus)
+ throw new ArgumentNullException(nameof(modulus));
+ if (null == inverse)
+ throw new ArgumentNullException(nameof(inverse));
+ if (inverse.IsAlias)
+ throw new InvalidOperationException("inverse is an alias");
+
+ NativeMethods.BigUInt_TryModuloInvert(NativePtr, modulus.NativePtr,
+ inverse.NativePtr, out bool result);
+ return result;
+ }
+
+ /// Attempts to calculate the inverse of a BigUInt with respect to
+ /// the specified modulus, returning whether or not the inverse was successful
+ /// and setting the inverse parameter to the inverse.
+ ///
+ /// Attempts to calculate the inverse of a BigUInt with respect to the
+ /// specified modulus, returning whether or not the inverse was successful
+ /// and setting the inverse parameter to the inverse. The original BigUInt
+ /// is not modified. The inverse parameter is resized if and only if its bit
+ /// count is smaller than the significant bit count of the modulus.
+ ///
+ /// The modulus to calculate the inverse with respect
+ /// to
+ /// Stores the inverse if the inverse operation was
+ /// successful
+ /// if inverse is null
+ /// if modulus is zero
+ /// if modulus is not greater than the
+ /// BigUInt value
+ /// if the inverse is an alias
+ /// which the function attempts to enlarge to fit the result
+ public bool TryModuloInvert(ulong modulus, BigUInt inverse)
+ {
+ if (null == inverse)
+ throw new ArgumentNullException(nameof(inverse));
+ if (inverse.IsAlias)
+ throw new InvalidOperationException("inverse is an alias");
+
+ NativeMethods.BigUInt_TryModuloInvert(NativePtr, modulus,
+ inverse.NativePtr, out bool result);
+ return result;
+ }
+
+ /// Duplicates the current BigUInt.
+ ///
+ /// Duplicates the current BigUInt. The bit count and the value of the given
+ /// BigUInt are set to be exactly the same as in the current one.
+ ///
+ /// The BigUInt to overwrite with the duplicate
+ /// if destination is null
+ /// if the destination BigUInt
+ /// is an alias
+ public void DuplicateTo(BigUInt destination)
+ {
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (destination.IsAlias)
+ throw new InvalidOperationException("destination is an alias");
+
+ NativeMethods.BigUInt_DuplicateTo(NativePtr, destination.NativePtr);
+ }
+
+ /// Duplicates a given BigUInt.
+ ///
+ /// Duplicates a given BigUInt. The bit count and the value of the current
+ /// BigUInt are set to be exactly the same as in the given one.
+ ///
+ /// The BigUInt to duplicate
+ /// if value is null
+ /// if the current BigUInt is
+ /// an alias
+ public void DuplicateFrom(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ NativeMethods.BigUInt_DuplicateFrom(NativePtr, value.NativePtr);
+ }
+
+ #region Operators
+
+ /// Returns a copy of the BigUInt value resized to the significant bit count.
+ ///
+ /// The operand to copy
+ /// if operand is null
+ public static BigUInt operator +(BigUInt operand)
+ {
+ if (null == operand)
+ throw new ArgumentNullException(nameof(operand));
+
+ return new BigUInt(operand);
+ }
+
+ /// Returns a negated copy of the BigUInt value.
+ ///
+ ///
+ /// Returns a negated copy of the BigUInt value. The bit count does not change.
+ ///
+ /// The operand to negate
+ /// if operand is null
+ public static BigUInt operator -(BigUInt operand)
+ {
+ if (null == operand)
+ throw new ArgumentNullException(nameof(operand));
+
+ NativeMethods.BigUInt_OperatorNeg(operand.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Returns an inverted copy of the BigUInt value.
+ ///
+ ///
+ /// Returns an inverted copy of the BigUInt value. The bit count does not change.
+ ///
+ /// The operand to invert
+ /// if operand is null
+ public static BigUInt operator ~(BigUInt operand)
+ {
+ if (null == operand)
+ throw new ArgumentNullException(nameof(operand));
+
+ NativeMethods.BigUInt_OperatorTilde(operand.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Increments the BigUInt and returns the incremented value.
+ ///
+ ///
+ /// Increments the BigUInt and returns the incremented value. The BigUInt will increment the bit count if needed to fit the
+ /// carry.
+ ///
+ /// The operand to increment
+ /// if operand is null
+ /// if BigUInt is an alias and a carry occurs requiring the BigUInt to
+ /// be resized
+ public static BigUInt operator ++(BigUInt operand)
+ {
+ if (null == operand)
+ throw new ArgumentNullException(nameof(operand));
+
+ NativeMethods.BigUInt_OperatorPlus(operand.NativePtr, operand: 1ul, result: out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Decrements the BigUInt and returns the decremented value.
+ ///
+ ///
+ /// Decrements the BigUInt and returns the decremented value. The bit count does not change.
+ ///
+ /// The operand to decrement
+ /// if operand is null
+ public static BigUInt operator --(BigUInt operand)
+ {
+ if (null == operand)
+ throw new ArgumentNullException(nameof(operand));
+
+ NativeMethods.BigUInt_OperatorMinus(operand.NativePtr, operand: 1ul, result: out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Adds two BigUInts and returns the sum.
+ ///
+ ///
+ /// Adds two BigUInts and returns the sum. The input operands are not modified. The bit count of the sum is set to be one
+ /// greater than the significant bit count of the larger of the two input operands.
+ ///
+ /// The first operand to add
+ /// The second operand to add
+ /// if operand1 or operand2 is null
+ public static BigUInt operator +(BigUInt operand1, BigUInt operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+
+ NativeMethods.BigUInt_OperatorPlus(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Adds a BigUInt and an unsigned integer and returns the sum.
+ ///
+ ///
+ /// Adds a BigUInt and an unsigned integer and returns the sum. The input operands are not modified. The bit count of the
+ /// sum is set to be one greater than the significant bit count of the larger of the two operands.
+ ///
+ /// The first operand to add
+ /// The second operand to add
+ /// if operand1 is null
+ public static BigUInt operator +(BigUInt operand1, ulong operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+
+ NativeMethods.BigUInt_OperatorPlus(operand1.NativePtr, operand2, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Subtracts two BigUInts and returns the difference.
+ ///
+ ///
+ /// Subtracts two BigUInts and returns the difference. The input operands are not modified. The bit count of the difference
+ /// is set to be the significant bit count of the larger of the two input operands.
+ ///
+ /// The first operand to subtract
+ /// The second operand to subtract
+ /// if operand1 or operand2 is null
+ public static BigUInt operator -(BigUInt operand1, BigUInt operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+
+ NativeMethods.BigUInt_OperatorMinus(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Subtracts a BigUInt and an unsigned integer and returns the difference.
+ ///
+ ///
+ /// Subtracts a BigUInt and an unsigned integer and returns the difference. The input operands are not modified. The bit
+ /// count of the difference is set to be the significant bit count of the larger of the two operands.
+ ///
+ /// The first operand to subtract
+ /// The second operand to subtract
+ /// if operand1 is null
+ public static BigUInt operator -(BigUInt operand1, ulong operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+
+ NativeMethods.BigUInt_OperatorMinus(operand1.NativePtr, operand2, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Multiplies two BigUInts and returns the product.
+ ///
+ ///
+ /// Multiplies two BigUInts and returns the product. The input operands are not modified. The bit count of the product is
+ /// set to be the sum of the significant bit counts of the two input operands.
+ ///
+ /// The first operand to multiply
+ /// The second operand to multiply
+ /// if operand1 or operand2 is null
+ public static BigUInt operator *(BigUInt operand1, BigUInt operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+
+ NativeMethods.BigUInt_OperatorMult(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Multiplies a BigUInt and an unsigned integer and returns the product.
+ ///
+ ///
+ /// Multiplies a BigUInt and an unsigned integer and returns the product. The input operands are not modified. The bit
+ /// count of the product is set to be the sum of the significant bit counts of the two input operands.
+ ///
+ /// The first operand to multiply
+ /// The second operand to multiply
+ /// if operand1 is null
+ public static BigUInt operator *(BigUInt operand1, ulong operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+
+ NativeMethods.BigUInt_OperatorMult(operand1.NativePtr, operand2, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Divides two BigUInts and returns the quotient.
+ ///
+ ///
+ /// Divides two BigUInts and returns the quotient. The input operands are not modified. The bit count of the quotient is
+ /// set to be the significant bit count of the first input operand.
+ ///
+ /// The first operand to divide
+ /// The second operand to divide
+ /// if operand1 or operand2 is null
+ /// if operand2 is zero
+ public static BigUInt operator /(BigUInt operand1, BigUInt operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+ if (operand2.IsZero)
+ throw new ArgumentException("operand2 is zero");
+
+ NativeMethods.BigUInt_OperatorDiv(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Divides a BigUInt and an unsigned integer and returns the quotient.
+ ///
+ ///
+ /// Divides a BigUInt and an unsigned integer and returns the quotient. The input operands are not modified. The bit count
+ /// of the quotient is set to be the significant bit count of the first input operand.
+ ///
+ /// The first operand to divide
+ /// The second operand to divide
+ /// if operand1 is null
+ /// if operand2 is zero
+ public static BigUInt operator /(BigUInt operand1, ulong operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (0 == operand2)
+ throw new ArgumentException("operand2 is zero");
+
+ NativeMethods.BigUInt_OperatorDiv(operand1.NativePtr, operand2, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Performs a bit-wise XOR operation between two BigUInts and returns the result.
+ ///
+ ///
+ /// Performs a bit-wise XOR operation between two BigUInts and returns the result. The input operands are not modified. The
+ /// bit count of the result is set to the maximum of the two input operand bit counts.
+ ///
+ /// The first operand to XOR
+ /// The second operand to XOR
+ /// if operand1 or operand2 is null
+ public static BigUInt operator ^(BigUInt operand1, BigUInt operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+
+ NativeMethods.BigUInt_OperatorXor(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Performs a bit-wise XOR operation between a BigUInt and an unsigned integer and returns the result.
+ ///
+ ///
+ /// Performs a bit-wise XOR operation between a BigUInt and an unsigned integer and returns the result. The input operands
+ /// are not modified. The bit count of the result is set to the maximum of the two input operand bit counts.
+ ///
+ /// The first operand to XOR
+ /// The second operand to XOR
+ /// if operand1 is null
+ public static BigUInt operator ^(BigUInt operand1, ulong operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+
+ NativeMethods.BigUInt_OperatorXor(operand1.NativePtr, operand2, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Performs a bit-wise AND operation between two BigUInts and returns the result.
+ ///
+ ///
+ /// Performs a bit-wise AND operation between two BigUInts and returns the result. The input operands are not modified. The
+ /// bit count of the result is set to the maximum of the two input operand bit counts.
+ ///
+ /// The first operand to AND
+ /// The second operand to AND
+ /// if operand1 or operand2 is null
+ public static BigUInt operator &(BigUInt operand1, BigUInt operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+
+ NativeMethods.BigUInt_OperatorAnd(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Performs a bit-wise AND operation between a BigUInt and an unsigned integer and returns the result.
+ ///
+ ///
+ /// Performs a bit-wise AND operation between a BigUInt and an unsigned integer and returns the result. The input operands
+ /// are not modified. The bit count of the result is set to the maximum of the two input operand bit counts.
+ ///
+ /// The first operand to AND
+ /// The second operand to AND
+ /// if operand1 is null
+ public static BigUInt operator &(BigUInt operand1, ulong operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+
+ NativeMethods.BigUInt_OperatorAnd(operand1.NativePtr, operand2, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Performs a bit-wise OR operation between two BigUInts and returns the result.
+ ///
+ ///
+ /// Performs a bit-wise OR operation between two BigUInts and returns the result. The input operands are not modified. The
+ /// bit count of the result is set to the maximum of the two input operand bit counts.
+ ///
+ /// The first operand to OR
+ /// The second operand to OR
+ /// if operand1 or operand2 is null
+ public static BigUInt operator |(BigUInt operand1, BigUInt operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (null == operand2)
+ throw new ArgumentNullException(nameof(operand2));
+
+ NativeMethods.BigUInt_OperatorOr(operand1.NativePtr, operand2.NativePtr, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Performs a bit-wise OR operation between a BigUInt and an unsigned integer and returns the result.
+ ///
+ ///
+ /// Performs a bit-wise OR operation between a BigUInt and an unsigned integer and returns the result. The input operands
+ /// are not modified. The bit count of the result is set to the maximum of the two input operand bit counts.
+ ///
+ /// The first operand to OR
+ /// The second operand to OR
+ /// if operand1 is null
+ public static BigUInt operator |(BigUInt operand1, ulong operand2)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+
+ NativeMethods.BigUInt_OperatorOr(operand1.NativePtr, operand2, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Returns a left-shifted copy of the BigUInt.
+ ///
+ ///
+ /// Returns a left-shifted copy of the BigUInt. The bit count of the returned value is the sum of the original significant
+ /// bit count and the shift amount.
+ ///
+ /// The operand to left-shift
+ /// The number of bits to shift by
+ /// if operand1 is null
+ /// if shift is negative
+ public static BigUInt operator <<(BigUInt operand1, int shift)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (shift < 0)
+ throw new ArgumentException("shift is negative");
+
+ NativeMethods.BigUInt_OperatorShiftLeft(operand1.NativePtr, shift, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Returns a right-shifted copy of the BigUInt.
+ ///
+ ///
+ /// Returns a right-shifted copy of the BigUInt. The bit count of the returned value is the original significant bit count
+ /// subtracted by the shift amount (clipped to zero if negative).
+ ///
+ /// The operand to right-shift
+ /// The number of bits to shift by
+ /// if operand1 is null
+ /// if shift is negative
+ public static BigUInt operator >>(BigUInt operand1, int shift)
+ {
+ if (null == operand1)
+ throw new ArgumentNullException(nameof(operand1));
+ if (shift < 0)
+ throw new ArgumentException("shift is negative");
+
+ NativeMethods.BigUInt_OperatorShiftRight(operand1.NativePtr, shift, out IntPtr resultptr);
+ BigUInt result = new BigUInt(resultptr);
+ return result;
+ }
+
+ /// Returns the BigUInt value as a double.
+ ///
+ /// Returns the BigUInt value as a double. Note that precision may be lost during the conversion.
+ ///
+ /// The value to convert
+ /// if value is null
+ public static explicit operator double(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ NativeMethods.BigUInt_ToDouble(value.NativePtr, out double result);
+ return result;
+ }
+
+ /// Returns the BigUInt value as a float.
+ ///
+ /// Returns the BigUInt value as a float. Note that precision may be lost during the conversion.
+ ///
+ /// The value to convert
+ /// if value is null
+ public static explicit operator float(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ double dblvalue = (double)value;
+ return unchecked((float)dblvalue);
+ }
+
+ /// Returns the lower 64-bits of a BigUInt value.
+ ///
+ /// Returns the lower 64-bits of a BigUInt value. Note that if the value is greater than 64-bits,
+ /// the higher bits are dropped.
+ ///
+ /// The value to convert
+ /// if value is null
+ public static explicit operator ulong(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ if (value.BitCount == 0)
+ return 0;
+
+ return value.Data(0);
+ }
+
+ /// Returns the lower 64-bits of a BigUInt value as a signed-integer.
+ ///
+ /// Returns the lower 64-bits of a BigUInt value as a signed-integer. Note that if the value is greater than
+ /// 64-bits, the result may be negative and the higher bits are dropped.
+ ///
+ /// The value to convert
+ /// if value is null
+ public static explicit operator long(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ ulong ulvalue = (ulong)value;
+ return unchecked((long)ulvalue);
+ }
+
+ /// Returns the lower 32-bits of a BigUInt value.
+ ///
+ /// Returns the lower 32-bits of a BigUInt value. Note that if the value is greater than 32-bits,
+ /// the higher bits are dropped.
+ ///
+ /// The value to convert
+ /// if value is null
+ public static explicit operator uint(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ ulong ulvalue = (ulong)value;
+ return unchecked((uint)ulvalue);
+ }
+
+ /// Returns the lower 32-bits of a BigUInt value as a signed-integer.
+ ///
+ /// Returns the lower 32-bits of a BigUInt value as a signed-integer. Note that if the value is greater than
+ /// 32-bits, the result may be negative and the higher bits are dropped.
+ ///
+ /// The value to convert
+ /// if value is null
+ public static explicit operator int(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ ulong ulvalue = (ulong)value;
+ return unchecked((int)ulvalue);
+ }
+
+ #endregion // Operators
+
+ #region IComparable methods
+
+ /// Compares two BigUInts and returns -1, 0, or 1 if the BigUInt is less-than, equal-to, or greater-than the
+ /// second operand respectively.
+ ///
+ ///
+ /// Compares two BigUInts and returns -1, 0, or 1 if the BigUInt is less-than, equal-to, or greater-than the second
+ /// operand respectively. The input operands are not modified.
+ ///
+ /// The value to compare against
+ public int CompareTo(BigUInt compare)
+ {
+ if (null == compare)
+ return 1;
+
+ NativeMethods.BigUInt_CompareTo(NativePtr, compare.NativePtr, out int result);
+ return result;
+ }
+
+ #endregion
+
+ #region IEquatable methods
+
+ /// Returns whether or not a BigUInt is equal to a second BigUInt.
+ ///
+ /// Returns whether or not a BigUInt is equal to a second BigUInt. The input operands are not modified.
+ ///
+ ///
+ /// The value to compare against
+ public bool Equals(BigUInt compare)
+ {
+ if (null == compare)
+ return false;
+
+ NativeMethods.BigUInt_Equals(NativePtr, compare.NativePtr, out bool result);
+ return result;
+ }
+
+ #endregion
+
+ #region Object overrides
+
+ /// Returns whether or not a BigUInt is equal to a second BigUInt.
+ ///
+ /// Returns whether or not a BigUInt is equal to a second BigUInt. The input operands are not modified.
+ ///
+ ///
+ /// The value to compare against
+ public override bool Equals(object compare)
+ {
+ BigUInt other = compare as BigUInt;
+ return Equals(other);
+ }
+
+ ///
+ /// Returns the BigUInt value as a hexadecimal string.
+ ///
+ public override string ToString()
+ {
+ NativeMethods.BigUInt_ToString(NativePtr, null, length: out ulong length);
+ StringBuilder buffer = new StringBuilder(checked((int)length));
+ NativeMethods.BigUInt_ToString(NativePtr, buffer, out length);
+ return buffer.ToString();
+ }
+
+ ///
+ /// Returns a hash-code based on the value of the BigUInt.
+ ///
+ public override int GetHashCode()
+ {
+ ulong[] data = new ulong[UInt64Count];
+ for (long i = 0; i < data.LongLength; i++)
+ {
+ data[i] = Data((ulong)i);
+ }
+
+ return Utilities.ComputeArrayHashCode(data);
+ }
+
+ #endregion
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.BigUInt_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/CKKSEncoder.cs b/bigpiseal3.5.1/dotnet/src/CKKSEncoder.cs
new file mode 100644
index 0000000000000000000000000000000000000000..99611ad612853b7d02400c4ab69a9e78a5d6f3bb
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/CKKSEncoder.cs
@@ -0,0 +1,449 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Provides functionality for encoding vectors of complex or real numbers into plaintext
+ /// polynomials to be encrypted and computed on using the CKKS scheme. If the polynomial
+ /// modulus degree is N, then CKKSEncoder converts vectors of N/2 complex numbers into
+ /// plaintext elements. Homomorphic operations performed on such encrypted vectors are
+ /// applied coefficient (slot-)wise, enabling powerful SIMD functionality for computations
+ /// that are vectorizable. This functionality is often called "batching" in the homomorphic
+ /// encryption literature.
+ ///
+ ///
+ ///
+ /// Mathematical Background
+ /// Mathematically speaking, if the polynomial modulus is X^N+1, N is a power of two, the
+ /// CKKSEncoder implements an approximation of the canonical embedding of the ring of
+ /// integers Z[X]/(X^N+1) into C^(N/2), where C denotes the complex numbers. The Galois
+ /// group of the extension is (Z/2NZ)* ~= Z/2Z x Z/(N/2) whose action on the primitive roots
+ /// of unity modulo CoeffModulus is easy to describe. Since the batching slots correspond
+ /// 1-to-1 to the primitive roots of unity, applying Galois automorphisms on the plaintext
+ /// acts by permuting the slots. By applying generators of the two cyclic subgroups of the
+ /// Galois group, we can effectively enable cyclic rotations and complex conjugations of
+ /// the encrypted complex vectors.
+ ///
+ ///
+ public class CKKSEncoder : NativeObject
+ {
+ ///
+ /// Creates a CKKSEncoder instance initialized with the specified SEALContext.
+ ///
+ /// The SEALContext
+ /// if context is null
+ /// if the context is not set or encryption parameters
+ /// are not valid
+ /// if scheme is not SchemeType.CKKS
+ public CKKSEncoder(SEALContext context)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+
+ SEALContext.ContextData contextData = context.FirstContextData;
+ if (contextData.Parms.Scheme != SchemeType.CKKS)
+ throw new ArgumentException("Unsupported scheme");
+
+ NativeMethods.CKKSEncoder_Create(context.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+
+ context_ = context;
+ }
+
+ ///
+ /// Encodes a vector of double-precision floating-point real numbers into a plaintext
+ /// polynomial.
+ ///
+ ///
+ /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process
+ /// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The enumeration of double-precision floating-point numbers
+ /// to encode
+ /// parmsId determining the encryption parameters to be used
+ /// by the result plaintext
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either values, parmsId or destionation are null.
+ /// if values has invalid size
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(IEnumerable values, ParmsId parmsId,
+ double scale, Plaintext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == values)
+ throw new ArgumentNullException(nameof(values));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ double[] valuearray = values.ToArray();
+ NativeMethods.CKKSEncoder_EncodeDouble(NativePtr, (ulong)valuearray.LongLength, valuearray,
+ parmsId.Block, scale, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Encodes a vector of double-precision floating-point complex numbers into a plaintext
+ /// polynomial.
+ ///
+ ///
+ /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process
+ /// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The enumeration of double-precision complex numbers
+ /// to encode
+ /// parmsId determining the encryption parameters to be used
+ /// by the result plaintext
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either values, parmsId or destionation are null.
+ /// if values has invalid size
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(IEnumerable values, ParmsId parmsId,
+ double scale, Plaintext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == values)
+ throw new ArgumentNullException(nameof(values));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ double[] valuearray = new double[values.LongCount() * 2];
+ ulong idx = 0;
+ foreach(Complex complex in values)
+ {
+ valuearray[idx++] = complex.Real;
+ valuearray[idx++] = complex.Imaginary;
+ }
+
+ // Note that we should pass values.Count as the length instead of valuearray.Length,
+ // since we are using two doubles in the array per element.
+ NativeMethods.CKKSEncoder_EncodeComplex(NativePtr, (ulong)values.LongCount(), valuearray,
+ parmsId.Block, scale, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Encodes a vector of double-precision floating-point real numbers into a plaintext
+ /// polynomial.
+ ///
+ ///
+ /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process
+ /// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ /// The encryption parameters used are the top level parameters for the given context.
+ ///
+ /// The enumeration of double-precision floating-point numbers
+ /// to encode
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either values or destionation are null.
+ /// if values has invalid size
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(IEnumerable values, double scale,
+ Plaintext destination, MemoryPoolHandle pool = null)
+ {
+ Encode(values, context_.FirstParmsId, scale, destination, pool);
+ }
+
+ ///
+ /// Encodes a vector of double-precision floating-point complex numbers into a plaintext
+ /// polynomial.
+ ///
+ ///
+ /// Append zeros if vector size is less than N/2. Dynamic memory allocations in the process
+ /// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ /// The encryption parameters used are the top level parameters for the given context.
+ ///
+ /// The enumeration of double-precision floating-point numbers
+ /// to encode
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either values or destionation are null.
+ /// if values has invalid size
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(IEnumerable values, double scale,
+ Plaintext destination, MemoryPoolHandle pool = null)
+ {
+ Encode(values, context_.FirstParmsId, scale, destination, pool);
+ }
+
+ ///
+ /// Encodes a double-precision floating-point real number into a plaintext polynomial.
+ ///
+ ///
+ /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the
+ /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The double-precision floating-point number to encode
+ /// parmsId determining the encryption parameters to be used
+ /// by the result plaintext
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either parmsId or destination are null
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(double value, ParmsId parmsId,
+ double scale, Plaintext destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.CKKSEncoder_Encode(NativePtr, value, parmsId.Block, scale, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Encodes a double-precision floating-point real number into a plaintext polynomial.
+ ///
+ ///
+ /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the
+ /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ /// The encryption parameters used are the top level parameters for the given context.
+ ///
+ /// The double-precision floating-point number to encode
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if destination is null
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(double value, double scale, Plaintext destination,
+ MemoryPoolHandle pool = null)
+ {
+ Encode(value, context_.FirstParmsId, scale, destination, pool);
+ }
+
+ ///
+ /// Encodes a double-precision floating-point complex number into a plaintext polynomial.
+ ///
+ ///
+ /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the
+ /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The double-precision complex number to encode
+ /// parmsId determining the encryption parameters to be used
+ /// by the result plaintext
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either parmsId or destination are null
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(Complex value, ParmsId parmsId, double scale,
+ Plaintext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.CKKSEncoder_Encode(NativePtr, value.Real, value.Imaginary, parmsId.Block, scale, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Encodes a double-precision floating-point complex number into a plaintext polynomial.
+ ///
+ ///
+ /// The number repeats for N/2 times to fill all slots. Dynamic memory allocations in the
+ /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ /// The encryption parameters used are the top level parameters for the given context.
+ ///
+ /// The double-precision complex number to encode
+ /// Scaling parameter defining encoding precision
+ /// The plaintext polynomial to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if destination is null
+ /// if scale is not strictly positive
+ /// if encoding is too large for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void Encode(Complex value, double scale, Plaintext destination,
+ MemoryPoolHandle pool = null)
+ {
+ Encode(value, context_.FirstParmsId, scale, destination, pool);
+ }
+
+ ///
+ /// Encodes an integer number into a plaintext polynomial without any scaling.
+ ///
+ ///
+ /// The number repeats for N/2 times to fill all slots.
+ ///
+ /// The integer number to encode
+ /// parmsId determining the encryption parameters to be used
+ /// by the result plaintext
+ /// The plaintext polynomial to overwrite with the result
+ /// if either parmsId or destionation are null
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ public void Encode(long value, ParmsId parmsId, Plaintext destination)
+ {
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.CKKSEncoder_Encode(NativePtr, value, parmsId.Block, destination.NativePtr);
+ }
+
+ ///
+ /// Encodes an integer number into a plaintext polynomial without any scaling.
+ ///
+ ///
+ /// The number repeats for N/2 times to fill all slots. The encryption parameters used are
+ /// the top level parameters for the given context.
+ ///
+ /// The integer number to encode
+ /// The plaintext polynomial to overwrite with the result
+ /// if destination is null
+ public void Encode(long value, Plaintext destination)
+ {
+ Encode(value, context_.FirstParmsId, destination);
+ }
+
+ ///
+ /// Decodes a plaintext polynomial into double-precision floating-point real numbers.
+ ///
+ ///
+ /// Dynamic memory allocations in the process are allocated from the memory pool pointed to
+ /// by the given MemoryPoolHandle.
+ ///
+ /// plain The plaintext to decode
+ /// The collection to be overwritten with the values in the slots
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain or destination are null
+ /// if plain is not in NTT form or is invalid for the
+ /// encryption parameters
+ /// if pool is uninitialized
+ public void Decode(Plaintext plain, ICollection destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ ulong destCount = 0;
+
+ // Allocate a big enough array to hold the result
+ double[] destArray = new double[SlotCount];
+ NativeMethods.CKKSEncoder_DecodeDouble(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr);
+
+ // Transfer result to actual destination; only destArray many slots were filled
+ destination.Clear();
+ for (ulong i = 0; i < destCount; i++)
+ {
+ destination.Add(destArray[i]);
+ }
+ }
+
+ ///
+ /// Decodes a plaintext polynomial into double-precision floating-point complex numbers.
+ ///
+ ///
+ /// Dynamic memory allocations in the process are allocated from the memory pool pointed to
+ /// by the given MemoryPoolHandle.
+ ///
+ /// plain The plaintext to decode
+ /// The collection to be overwritten with the values in the slots
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain or destination are null
+ /// if plain is not in NTT form or is invalid for the
+ /// encryption parameters
+ /// if pool is uninitialized
+ public void Decode(Plaintext plain, ICollection destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ ulong destCount = 0;
+
+ // Allocate a big enough array to hold the result
+ double[] destArray = new double[SlotCount * 2];
+ NativeMethods.CKKSEncoder_DecodeComplex(NativePtr, plain.NativePtr, ref destCount, destArray, poolPtr);
+
+ // Transfer result to actual destination
+ destination.Clear();
+ for (ulong i = 0; i < destCount; i++)
+ {
+ destination.Add(new Complex(destArray[i * 2], destArray[i * 2 + 1]));
+ }
+ }
+
+ ///
+ /// Returns the number of complex numbers encoded.
+ ///
+ public ulong SlotCount
+ {
+ get
+ {
+ NativeMethods.CKKSEncoder_SlotCount(NativePtr, out ulong slotCount);
+ return slotCount;
+ }
+ }
+
+ ///
+ /// SEALContext for this encoder
+ ///
+ private readonly SEALContext context_ = null;
+
+ ///
+ /// Destroy native object
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.CKKSEncoder_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/Ciphertext.cs b/bigpiseal3.5.1/dotnet/src/Ciphertext.cs
new file mode 100644
index 0000000000000000000000000000000000000000..37cf1a4dc35e71fcf096734c2fafd1b8d14340b0
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Ciphertext.cs
@@ -0,0 +1,680 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Class to store a ciphertext element. The data for a ciphertext consists
+ /// of two or more polynomials, which are in Microsoft SEAL stored in a CRT
+ /// form with respect to the factors of the coefficient modulus. This data
+ /// itself is not meant to be modified directly by the user, but is instead
+ /// operated on by functions in the Evaluator class. The size of the backing
+ /// array of a ciphertext depends on the encryption parameters and the size
+ /// of the ciphertext (at least 2). If the PolyModulusDegree encryption
+ /// parameter is N, and the number of primes in the CoeffModulus encryption
+ /// parameter is K, then the ciphertext backing array requires precisely
+ /// 8*N*K*size bytes of memory. A ciphertext also carries with it the
+ /// parmsId of its associated encryption parameters, which is used to check
+ /// the validity of the ciphertext for homomorphic operations and decryption.
+ ///
+ ///
+ ///
+ /// Memory Management
+ /// The size of a ciphertext refers to the number of polynomials it contains,
+ /// whereas its capacity refers to the number of polynomials that fit in the
+ /// current memory allocation. In high-performance applications unnecessary
+ /// re-allocations should be avoided by reserving enough memory for the
+ /// ciphertext to begin with either by providing the desired capacity to the
+ /// constructor as an extra argument, or by calling the reserve function at
+ /// any time.
+ ///
+ ///
+ /// Thread Safety
+ /// In general, reading from ciphertext is thread-safe as long as no other
+ /// thread is concurrently mutating it. This is due to the underlying data
+ /// structure storing the ciphertext not being thread-safe.
+ ///
+ ///
+ /// See Plaintext for the class that stores plaintexts.
+ public class Ciphertext :
+ NativeObject,
+ ISerializableObject,
+ ISettable
+ {
+ ///
+ /// Constructs an empty ciphertext allocating no memory.
+ ///
+ public Ciphertext() : this(pool: null)
+ {
+ }
+
+ ///
+ /// Constructs an empty ciphertext allocating no memory.
+ ///
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if pool is uninitialized
+ public Ciphertext(MemoryPoolHandle pool)
+ {
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Ciphertext_Create1(poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs an empty ciphertext with capacity 2. In addition to the
+ /// capacity, the allocation size is determined by the highest-level
+ /// parameters associated to the given SEALContext.
+ ///
+ /// The SEALContext
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if context is null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if pool is uninitialized
+ public Ciphertext(SEALContext context, MemoryPoolHandle pool = null)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Ciphertext_Create3(context.NativePtr, poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs an empty ciphertext with capacity 2. In addition to the
+ /// capacity, the allocation size is determined by the encryption parameters
+ /// with given ParmsId.
+ ///
+ /// The SEALContext
+ /// The ParmsId corresponding to the encryption
+ /// parameters to be used
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either context or parmsId are null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public Ciphertext(SEALContext context, ParmsId parmsId, MemoryPoolHandle pool = null)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Ciphertext_Create4(context.NativePtr, parmsId.Block, poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs an empty ciphertext with given capacity. In addition to
+ /// the capacity, the allocation size is determined by the given
+ /// encryption parameters.
+ ///
+ /// The SEALContext
+ /// The ParmsId corresponding to the encryption
+ /// parameters to be used
+ /// The capacity
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either context or parmsId are null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if sizeCapacity is less than 2 or too large
+ /// if pool is uninitialized
+ public Ciphertext(SEALContext context, ParmsId parmsId, ulong sizeCapacity,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Ciphertext_Create5(context.NativePtr, parmsId.Block, sizeCapacity, poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs a new ciphertext by copying a given one.
+ ///
+ /// The ciphertext to copy from
+ /// if copy is null
+ public Ciphertext(Ciphertext copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.Ciphertext_Create2(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs a new ciphertext by copying a given one.
+ ///
+ /// The ciphertext to copy from
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either copy or pool are null
+ /// if pool is uninitialized
+ public Ciphertext(Ciphertext copy, MemoryPoolHandle pool) : this(pool)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ Set(copy);
+ }
+
+ ///
+ /// Constructs a new ciphertext by initializing it with a native
+ /// object pointer.
+ ///
+ /// The native Ciphertext pointer
+ /// Whether this object owns the native pointer
+ internal Ciphertext(IntPtr ciphertextPtr, bool owned = true)
+ : base(ciphertextPtr, owned)
+ {
+ }
+
+ ///
+ /// Allocates enough memory to accommodate the backing array of a ciphertext
+ /// with given capacity. In addition to the capacity, the allocation size is
+ /// determined by the encryption parameters corresponing to the given
+ /// parmsId.
+ ///
+ /// The SEALContext
+ /// The ParmsId corresponding to the encryption
+ /// parameters to be used
+ /// The capacity
+ /// if either context or parmsId are null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if sizeCapacity is less than 2 or too large
+ public void Reserve(SEALContext context, ParmsId parmsId, ulong sizeCapacity)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+
+ NativeMethods.Ciphertext_Reserve(NativePtr, context.NativePtr, parmsId.Block, sizeCapacity);
+ }
+
+ ///
+ /// Allocates enough memory to accommodate the backing array of a ciphertext
+ /// with given capacity. In addition to the capacity, the allocation size is
+ /// determined by the highest-level parameters associated to the given
+ /// SEALContext.
+ ///
+ /// The SEALContext
+ /// The capacity
+ /// if context is null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if sizeCapacity is less than 2 or too large
+ public void Reserve(SEALContext context, ulong sizeCapacity)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.Ciphertext_Reserve(NativePtr, context.NativePtr, sizeCapacity);
+ }
+
+ ///
+ /// Allocates enough memory to accommodate the backing array of a ciphertext
+ /// with given capacity. In addition to the capacity, the allocation size is
+ /// determined by the current encryption parameters.
+ ///
+ /// The capacity
+ /// if sizeCapacity is less than 2 or too large
+ public void Reserve(ulong sizeCapacity)
+ {
+ NativeMethods.Ciphertext_Reserve(NativePtr, sizeCapacity);
+ }
+
+ ///
+ /// Resizes the ciphertext to given size, reallocating if the capacity
+ /// of the ciphertext is too small. The ciphertext parameters are
+ /// determined by the given SEALContext and parmsId.
+ ///
+ /// This function is mainly intended for internal use and is called
+ /// automatically by functions such as Evaluator::multiply and
+ /// Evaluator::relinearize. A normal user should never have a reason
+ /// to manually resize a ciphertext.
+ ///
+ /// The SEALContext
+ /// The ParmsId corresponding to the encryption
+ /// parameters to be used
+ /// The new size
+ /// if either context or parmsId are null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if size is less than 2 or too large
+ public void Resize(SEALContext context, ParmsId parmsId, ulong size)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+
+ NativeMethods.Ciphertext_Resize(NativePtr, context.NativePtr, parmsId.Block, size);
+ }
+
+ ///
+ /// Resizes the ciphertext to given size, reallocating if the capacity
+ /// of the ciphertext is too small. The ciphertext parameters are
+ /// determined by the highest-level parameters associated to the given
+ /// SEALContext.
+ ///
+ /// This function is mainly intended for internal use and is called
+ /// automatically by functions such as Evaluator::multiply and
+ /// Evaluator::relinearize. A normal user should never have a reason
+ /// to manually resize a ciphertext.
+ ///
+ /// The SEALContext
+ /// The new size
+ /// if context is null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if size is less than 2 or too large
+ public void Resize(SEALContext context, ulong size)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.Ciphertext_Resize(NativePtr, context.NativePtr, size);
+ }
+
+ ///
+ /// Resizes the ciphertext to given size, reallocating if the capacity
+ /// of the ciphertext is too small.
+ ///
+ /// This function is mainly intended for internal use and is called
+ /// automatically by functions such as Evaluator::multiply and
+ /// Evaluator::relinearize. A normal user should never have a reason
+ /// to manually resize a ciphertext.
+ ///
+ /// The new size
+ /// if size is less than 2 or too large
+ public void Resize(ulong size)
+ {
+ NativeMethods.Ciphertext_Resize(NativePtr, size);
+ }
+
+ ///
+ /// Resizes the ciphertext to the given size, poly modulus degree and
+ /// coefficient mod count. This is a helper for loading a ciphertext
+ /// from a stream.
+ ///
+ /// The new size
+ /// The new poly modulus degree
+ /// The new coefficient mod count
+ private void Resize(ulong size, ulong polyModulusDegree, ulong coeffModCount)
+ {
+ NativeMethods.Ciphertext_Resize(NativePtr, size, polyModulusDegree, coeffModCount);
+ }
+
+ ///
+ /// Resets the ciphertext. This function releases any memory allocated
+ /// by the ciphertext, returning it to the memory pool. It also sets all
+ /// encryption parameter specific size information to zero.
+ ///
+ public void Release()
+ {
+ NativeMethods.Ciphertext_Release(NativePtr);
+ }
+
+ ///
+ /// Copies a given ciphertext to the current one.
+ ///
+ /// The ciphertext to copy from
+ /// if assign is null
+ public void Set(Ciphertext assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.Ciphertext_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Returns the polynomial coefficient at a particular index in the ciphertext data. If the
+ /// polynomial modulus has degree N, and the number of primes in the coefficient modulus is K, then
+ /// the ciphertext contains size*N*K coefficients. Thus, the index has a range of [0, size*N*K).
+ ///
+ /// The index of the coefficient
+ /// if coeffIndex is out of range
+ public ulong this[ulong coeffIndex]
+ {
+ get
+ {
+ try
+ {
+ NativeMethods.Ciphertext_GetDataAt(NativePtr, coeffIndex, out ulong value);
+ return value;
+ }
+ catch (COMException ex)
+ {
+ if ((uint)ex.HResult == NativeMethods.Errors.HRInvalidIndex)
+ throw new IndexOutOfRangeException(nameof(coeffIndex), ex);
+ throw;
+ }
+ }
+
+ set
+ {
+ try
+ {
+ NativeMethods.Ciphertext_SetDataAt(NativePtr, coeffIndex, value);
+ }
+ catch (COMException ex)
+ {
+ if ((uint)ex.HResult == NativeMethods.Errors.HRInvalidIndex)
+ throw new IndexOutOfRangeException(nameof(coeffIndex), ex);
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Get the value of a coefficient at the given index from
+ /// a particular polynomial in the ciphertext
+ /// data. Note that Microsoft SEAL stores each polynomial in the ciphertext
+ /// modulo all of the K primes in the coefficient modulus. The data
+ /// returned by this function is to the beginning (constant coefficient)
+ /// of the first one of these K polynomials.
+ ///
+ /// The index of the polynomial in the ciphertext
+ /// The index of the polynomial data
+ /// if polyIndex is less than 0 or bigger
+ /// than the size of the ciphertext
+ /// if coeffIndex is less than 0 or bigger
+ /// than the size of the ciphertext
+ public ulong this[ulong polyIndex, ulong coeffIndex]
+ {
+ get
+ {
+ try
+ {
+ NativeMethods.Ciphertext_GetDataAt(NativePtr, polyIndex, coeffIndex, out ulong data);
+ return data;
+ }
+ catch(COMException ex)
+ {
+ if ((uint)ex.HResult == NativeMethods.Errors.HRInvalidIndex)
+ throw new IndexOutOfRangeException("polyIndex or coeffIndex out of range", ex);
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Returns the number of primes in the coefficient modulus of the
+ /// associated encryption parameters. This directly affects the
+ /// allocation size of the ciphertext.
+ ///
+ public ulong CoeffModulusSize
+ {
+ get
+ {
+ NativeMethods.Ciphertext_CoeffModulusSize(NativePtr, out ulong coeffModCount);
+ return coeffModCount;
+ }
+ }
+
+
+ ///
+ /// Returns the degree of the polynomial modulus of the associated
+ /// encryption parameters.This directly affects the allocation size
+ /// of the ciphertext.
+ ///
+ public ulong PolyModulusDegree
+ {
+ get
+ {
+ NativeMethods.Ciphertext_PolyModulusDegree(NativePtr, out ulong polyModulusDegree);
+ return polyModulusDegree;
+ }
+ }
+
+ ///
+ /// Returns the capacity of the allocation. This means the largest size
+ /// of the ciphertext that can be stored in the current allocation with
+ /// the current encryption parameters.
+ ///
+ public ulong SizeCapacity
+ {
+ get
+ {
+ NativeMethods.Ciphertext_SizeCapacity(NativePtr, out ulong sizeCapacity);
+ return sizeCapacity;
+ }
+ }
+
+ ///
+ /// Returns the size of the ciphertext.
+ ///
+ public ulong Size
+ {
+ get
+ {
+ NativeMethods.Ciphertext_Size(NativePtr, out ulong size);
+ return size;
+ }
+ }
+
+ ///
+ /// Check whether the current ciphertext is transparent, i.e. does not require
+ /// a secret key to decrypt. In typical security models such transparent
+ /// ciphertexts would not be considered to be valid. Starting from the second
+ /// polynomial in the current ciphertext, this function returns true if all
+ /// following coefficients are identically zero. Otherwise, returns false.
+ ///
+ public bool IsTransparent
+ {
+ get
+ {
+ NativeMethods.Ciphertext_IsTransparent(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns an upper bound on the size of the ciphertext, as if it was written
+ /// to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.Ciphertext_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the ciphertext to an output stream.
+ ///
+ /// Saves the ciphertext to an output stream. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the ciphertext to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.Ciphertext_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ /// Loads a ciphertext from an input stream overwriting the current
+ /// ciphertext.
+ ///
+ /// Loads a ciphertext from an input stream overwriting the current ciphertext.
+ /// No checking of the validity of the ciphertext data against encryption
+ /// parameters is performed. This function should not be used unless the
+ /// ciphertext comes from a fully trusted source.
+ ///
+ /// The SEALContext
+ /// The stream to load the ciphertext from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long UnsafeLoad(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.Ciphertext_UnsafeLoad(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ /// Loads a ciphertext from an input stream overwriting the current
+ /// ciphertext.
+ ///
+ /// Loads a ciphertext from an input stream overwriting the current ciphertext.
+ /// The loaded ciphertext is verified to be valid for the given SEALContext.
+ ///
+ /// The SEALContext
+ /// The stream to load the ciphertext from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long Load(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.Ciphertext_Load(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ ///
+ /// Returns whether the ciphertext is in NTT form.
+ ///
+ public bool IsNTTForm
+ {
+ get
+ {
+ NativeMethods.Ciphertext_IsNTTForm(NativePtr, out bool isNTTForm);
+ return isNTTForm;
+ }
+
+ private set
+ {
+ NativeMethods.Ciphertext_SetIsNTTForm(NativePtr, value);
+ }
+ }
+
+ ///
+ /// Returns a copy of ParmsId.
+ ///
+ public ParmsId ParmsId
+ {
+ get
+ {
+ ParmsId parmsId = new ParmsId();
+ NativeMethods.Ciphertext_ParmsId(NativePtr, parmsId.Block);
+ return parmsId;
+ }
+ private set
+ {
+ NativeMethods.Ciphertext_SetParmsId(NativePtr, value.Block);
+ }
+ }
+
+ ///
+ /// Returns a reference to the scale. This is only needed when using the
+ /// CKKS encryption scheme. The user should have little or no reason to ever
+ /// change the scale by hand.
+ ///
+ public double Scale
+ {
+ get
+ {
+ NativeMethods.Ciphertext_Scale(NativePtr, out double scale);
+ return scale;
+ }
+ set
+ {
+ NativeMethods.Ciphertext_SetScale(NativePtr, value);
+ }
+ }
+
+ ///
+ /// Returns the currently used MemoryPoolHandle.
+ ///
+ public MemoryPoolHandle Pool
+ {
+ get
+ {
+ NativeMethods.Ciphertext_Pool(NativePtr, out IntPtr pool);
+ MemoryPoolHandle handle = new MemoryPoolHandle(pool);
+ return handle;
+ }
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.Ciphertext_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/Decryptor.cs b/bigpiseal3.5.1/dotnet/src/Decryptor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ed8a7fa8a02d48837872515dd11f563ae552127b
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Decryptor.cs
@@ -0,0 +1,128 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Decrypts Ciphertext objects into Plaintext objects. Constructing a Decryptor requires
+ /// a SEALContext with valid encryption parameters, and the secret key. The Decryptor is
+ /// also used to compute the invariant noise budget in a given ciphertext.
+ ///
+ ///
+ ///
+ /// Overloads
+ /// For the decrypt function we provide two overloads concerning the memory pool used in
+ /// allocations needed during the operation. In one overload the global memory pool is used
+ /// for this purpose, and in another overload the user can supply a MemoryPoolHandle
+ /// to to be used instead. This is to allow one single Decryptor to be used concurrently by
+ /// several threads without running into thread contention in allocations taking place during
+ /// operations. For example, one can share one single Decryptor across any number of threads,
+ /// but in each thread call the decrypt function by giving it a thread-local MemoryPoolHandle
+ /// to use. It is important for a developer to understand how this works to avoid unnecessary
+ /// performance bottlenecks.
+ ///
+ ///
+ /// NTT form
+ /// When using the BFV scheme (SchemeType.BFV), all plaintext and ciphertexts should
+ /// remain by default in the usual coefficient representation, i.e. not in NTT form.
+ /// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts
+ /// should remain by default in NTT form. We call these scheme-specific NTT states the
+ /// "default NTT form". Decryption requires the input ciphertexts to be in the default
+ /// NTT form, and will throw an exception if this is not the case.
+ ///
+ ///
+ public class Decryptor : NativeObject
+ {
+ ///
+ /// Creates a Decryptor instance initialized with the specified SEALContext
+ /// and secret key.
+ ///
+ /// The SEALContext
+ /// The secret key
+ /// if either context or secretKey are null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if secretKey is not valid
+ public Decryptor(SEALContext context, SecretKey secretKey)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (null == secretKey)
+ throw new ArgumentNullException(nameof(secretKey));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+ if (!ValCheck.IsValidFor(secretKey, context))
+ throw new ArgumentException("Secret key is not valid for encryption parameters");
+
+ NativeMethods.Decryptor_Create(context.NativePtr, secretKey.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Decrypts a Ciphertext and stores the result in the destination parameter. Dynamic
+ /// memory allocations in the process are allocated from the memory pool pointed to by
+ /// the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to decrypt
+ /// The plaintext to overwrite with the decrypted ciphertext
+ /// if either encrypted or destination are null
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if pool is uninitialized
+ public void Decrypt(Ciphertext encrypted, Plaintext destination)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Decryptor_Decrypt(NativePtr, encrypted.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Computes the invariant noise budget (in bits) of a ciphertext. The invariant noise
+ /// budget measures the amount of room there is for the noise to grow while ensuring
+ /// correct decryptions. Dynamic memory allocations in the process are allocated from
+ /// the memory pool pointed to by the given MemoryPoolHandle. This function works only
+ /// with the BFV scheme.
+ ///
+ ///
+ ///
+ /// Invariant Noise Budget
+ /// The invariant noise polynomial of a ciphertext is a rational coefficient polynomial,
+ /// such that a ciphertext decrypts correctly as long as the coefficients of the invariant
+ /// noise polynomial are of absolute value less than 1/2. Thus, we call the infinity-norm
+ /// of the invariant noise polynomial the invariant noise, and for correct decryption require
+ /// it to be less than 1/2. If v denotes the invariant noise, we define the invariant noise
+ /// budget as -log2(2v). Thus, the invariant noise budget starts from some initial value,
+ /// which depends on the encryption parameters, and decreases when computations are performed.
+ /// When the budget reaches zero, the ciphertext becomes too noisy to decrypt correctly.
+ ///
+ ///
+ /// The ciphertext
+ /// if encrypted is null
+ /// if the scheme is not BFV
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is in NTT form
+ /// if pool is uninitialized
+ public int InvariantNoiseBudget(Ciphertext encrypted)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+
+ NativeMethods.Decryptor_InvariantNoiseBudget(NativePtr, encrypted.NativePtr, out int result);
+ return result;
+ }
+
+ ///
+ /// Destroy native object
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.Decryptor_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/EncryptionParameterQualifiers.cs b/bigpiseal3.5.1/dotnet/src/EncryptionParameterQualifiers.cs
new file mode 100644
index 0000000000000000000000000000000000000000..34a6a23dab3a69868f6e3f2435f736b82ff82aa4
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/EncryptionParameterQualifiers.cs
@@ -0,0 +1,216 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Text;
+using Microsoft.Research.SEAL.Tools;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Stores a set of attributes (qualifiers) of a set of encryption parameters.
+ ///
+ ///
+ ///
+ /// Stores a set of attributes (qualifiers) of a set of encryption parameters.
+ /// These parameters are mainly used internally in various parts of the library,
+ /// e.g., to determine which algorithmic optimizations the current support.
+ /// The qualifiers are automatically created by the
+ /// class, silently passed on to classes such as ,
+ /// , and , and the only way
+ /// to change them is by changing the encryption parameters themselves. In
+ /// other words, a user will never have to create their own instance of this
+ /// class, and in most cases never have to worry about it at all.
+ ///
+ public class EncryptionParameterQualifiers : NativeObject
+ {
+ ///
+ /// Create a copy of an existing instance of EncryptionParameterQualifiers
+ ///
+ /// Original object to copy
+ public EncryptionParameterQualifiers(EncryptionParameterQualifiers copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.EPQ_Create(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Create an instance of EncryptionParameterQualifiers through a pointer to
+ /// a native object.
+ ///
+ /// Pointer to native EncryptionParameterQualifiers.
+ /// Whether this instance owns the native pointer.
+ internal EncryptionParameterQualifiers(IntPtr ptr, bool owned = true)
+ : base(ptr, owned)
+ {
+ }
+
+ ///
+ /// If the encryption parameters are set in a way that is considered valid by SEAL,
+ /// the variable ParametersSet is set to true.
+ ///
+ public bool ParametersSet
+ {
+ get
+ {
+ NativeMethods.EPQ_ParametersSet(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// If the encryption parameters are set in a way that is considered valid by SEAL, return "success".
+ /// If the encryption parameters are set but not validated yet, return "none".
+ /// Otherwise, return a brief reason.
+ ///
+ public string ParametersErrorName()
+ {
+ NativeMethods.EPQ_ParameterErrorName(NativePtr, null, out ulong length);
+ StringBuilder buffer = new StringBuilder(checked((int)length));
+ NativeMethods.EPQ_ParameterErrorName(NativePtr, buffer, out length);
+ return buffer.ToString();
+ }
+
+ ///
+ /// If the encryption parameters are set in a way that is considered valid by SEAL, return "valid".
+ /// Otherwise, return a comprehensive reason.
+ ///
+ public string ParametersErrorMessage()
+ {
+ NativeMethods.EPQ_ParameterErrorMessage(NativePtr, null, out ulong length);
+ StringBuilder buffer = new StringBuilder(checked((int)length));
+ NativeMethods.EPQ_ParameterErrorMessage(NativePtr, buffer, out length);
+ return buffer.ToString();
+ }
+
+ ///
+ /// Tells whether FFT can be used for polynomial multiplication.
+ ///
+ ///
+ ///
+ /// Tells whether FFT can be used for polynomial multiplication. If the polynomial modulus
+ /// is of the form X^N+1, where N is a power of two, then FFT can be used for fast
+ /// multiplication of polynomials modulo the polynomial modulus. In this case the
+ /// variable UsingFFT will be set to true. However, currently Microsoft SEAL requires this
+ /// to be the case for the parameters to be valid. Therefore, ParametersSet can only
+ /// be true if UsingFFT is true.
+ ///
+ public bool UsingFFT
+ {
+ get
+ {
+ NativeMethods.EPQ_UsingFFT(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Tells whether NTT can be used for polynomial multiplication.
+ ///
+ ///
+ ///
+ /// Tells whether NTT can be used for polynomial multiplication. If the primes in the
+ /// coefficient modulus are congruent to 1 modulo 2N, where X^N+1 is the polynomial
+ /// modulus and N is a power of two, then the number-theoretic transform (NTT) can be
+ /// used for fast multiplications of polynomials modulo the polynomial modulus and
+ /// coefficient modulus.In this case the variable UsingNTT will be set to true. However,
+ /// currently Microsoft SEAL requires this to be the case for the parameters to be valid.
+ /// Therefore, ParametersSet can only be true if UsingNTT is true.
+ ///
+ public bool UsingNTT
+ {
+ get
+ {
+ NativeMethods.EPQ_UsingNTT(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Tells whether batching is supported by the encryption parameters.
+ ///
+ ///
+ ///
+ /// Tells whether batching is supported by the encryption parameters. If the plaintext
+ /// modulus is congruent to 1 modulo 2N, where X^N+1 is the polynomial modulus and N is
+ /// a power of two, then it is possible to use the BatchEncoder class to view plaintext
+ /// elements as 2-by-(N/2) matrices of integers modulo the plaintext modulus.This is
+ /// called batching, and allows the user to operate on the matrix elements(slots) in
+ /// a SIMD fashion, and rotate the matrix rows and columns.When the computation is
+ /// easily vectorizable, using batching can yield a huge performance boost.If the
+ /// encryption parameters support batching, the variable UsingBatching is set to true.
+ ///
+ public bool UsingBatching
+ {
+ get
+ {
+ NativeMethods.EPQ_UsingBatching(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Tells whether fast plain lift is supported by the encryption parameters.
+ ///
+ ///
+ ///
+ /// Tells whether fast plain lift is supported by the encryption parameters. A certain
+ /// performance optimization in multiplication of a ciphertext by a plaintext
+ /// (Evaluator.MultiplyPlain) and in transforming a plaintext element to NTT domain
+ /// (Evaluator.TransformToNTT) can be used when the plaintext modulus is smaller than
+ /// each prime in the coefficient modulus. In this case the variable UsingFastPlainLift
+ /// is set to true.
+ ///
+ public bool UsingFastPlainLift
+ {
+ get
+ {
+ NativeMethods.EPQ_UsingFastPlainLift(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Tells whether the coefficient modulus consists of a set of primes that are in
+ /// decreasing order.
+ ///
+ ///
+ ///
+ /// Tells whether the coefficient modulus consists of a set of primes that are in
+ /// decreasing order. If this is true, certain modular reductions in base conversion
+ /// can be omitted, improving performance.
+ ///
+ public bool UsingDescendingModulusChain
+ {
+ get
+ {
+ NativeMethods.EPQ_UsingDescendingModulusChain(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Tells whether the encryption parameters are secure based on the standard
+ /// parameters from HomomorphicEncryption.org security standard.
+ ///
+ public SecLevelType SecLevel
+ {
+ get
+ {
+ NativeMethods.EPQ_SecLevel(NativePtr, out int result);
+ return (SecLevelType)result;
+ }
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.EPQ_Destroy(NativePtr);
+ }
+ }
+}
\ No newline at end of file
diff --git a/bigpiseal3.5.1/dotnet/src/EncryptionParameters.cs b/bigpiseal3.5.1/dotnet/src/EncryptionParameters.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1e55bd9405981a5bd5f29d56b52a1d0fb41398b3
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/EncryptionParameters.cs
@@ -0,0 +1,414 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Describes the type of encryption scheme to be used.
+ ///
+ public enum SchemeType : byte
+ {
+ ///
+ /// No scheme set; cannot be used for encryption
+ ///
+ None = 0x0,
+
+ ///
+ /// Brakerski/Fan-Vercauteren scheme
+ ///
+ BFV = 0x1,
+
+ ///
+ /// Cheon-Kim-Kim-Song scheme
+ ///
+ CKKS = 0x2
+ }
+
+ ///
+ /// Represents the user-customizable encryption scheme settings.
+ ///
+ ///
+ ///
+ /// Represents user-customizable encryption scheme settings. The parameters (most
+ /// importantly PolyModulus, CoeffModulus, PlainModulus) significantly affect the
+ /// performance, capabilities, and security of the encryption scheme. Once an
+ /// instance of EncryptionParameters is populated with appropriate parameters, it
+ /// can be used to create an instance of the class,
+ /// which verifies the validity of the parameters, and performs necessary
+ /// pre-computations.
+ ///
+ ///
+ /// Picking appropriate encryption parameters is essential to enable a particular
+ /// application while balancing performance and security. Some encryption settings
+ /// will not allow some inputs (e.g. attempting to encrypt a polynomial with more
+ /// coefficients than PolyModulus or larger coefficients than PlainModulus) or
+ /// support the desired computations (with noise growing too fast due to too large
+ /// PlainModulus and too small CoeffModulus).
+ ///
+ ///
+ /// The EncryptionParameters class maintains at all times a 256-bit hash of the
+ /// currently set encryption parameters called the ParmsId. This hash acts as
+ /// a unique identifier of the encryption parameters and is used by all further
+ /// objects created for these encryption parameters. The ParmsId is not intended
+ /// to be directly modified by the user but is used internally for pre-computation
+ /// data lookup and input validity checks. In modulus switching the user can use
+ /// the ParmsId to keep track of the chain of encryption parameters. The ParmsId is
+ /// not exposed in the public API of EncryptionParameters, but can be accessed
+ /// through the class once the SEALContext
+ /// has been created.
+ ///
+ ///
+ /// In general, reading from EncryptionParameters is thread-safe, while mutating
+ /// is not.
+ ///
+ ///
+ /// Choosing inappropriate encryption parameters may lead to an encryption scheme
+ /// that is not secure, does not perform well, and/or does not support the input
+ /// and computation of the desired application. We highly recommend consulting an
+ /// expert in RLWE-based encryption when selecting parameters, as this is where
+ /// inexperienced users seem to most often make critical mistakes.
+ ///
+ ///
+ public class EncryptionParameters : NativeObject, IEquatable
+ {
+ ///
+ /// Creates an empty set of encryption parameters.
+ ///
+ ///
+ /// Scheme for the encryption parameters
+ public EncryptionParameters(SchemeType scheme = SchemeType.None)
+ {
+ NativeMethods.EncParams_Create((byte)scheme, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates an empty set of encryption parameters.
+ ///
+ /// Scheme for the encryption parameters
+ /// if scheme is not supported
+ public EncryptionParameters(byte scheme)
+ {
+ NativeMethods.EncParams_Create(scheme, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a copy of a given instance of EncryptionParameters.
+ ///
+ /// The EncryptionParameters to copy from
+ /// if copy is null
+ public EncryptionParameters(EncryptionParameters copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.EncParams_Create(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Create an instance of Encryption Parameters through a pointer to a
+ /// native object.
+ ///
+ /// Native encryption parameters
+ /// Whether this instance owns the native pointer
+ internal EncryptionParameters(IntPtr ptr, bool owned = true)
+ : base(ptr, owned)
+ {
+ }
+
+ ///
+ /// Overwrites the EncryptionParameters instance with a copy of a given
+ /// instance.
+ ///
+ /// The EncryptionParameters to copy from
+ /// if assign is null
+ public void Set(EncryptionParameters assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.EncParams_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Returns or Sets the degree of the polynomial modulus parameter.
+ ///
+ ///
+ /// Sets the degree of the polynomial modulus parameter to the specified value.
+ /// The polynomial modulus directly affects the number of coefficients in plaintext
+ /// polynomials, the size of ciphertext elements, the computational performance of
+ /// the scheme (bigger is worse), and the security level(bigger is better). In SEAL
+ /// the degree of the polynomial modulus must be a power of 2 (e.g. 1024, 2048, 4096,
+ /// 8192, 16384, or 32768).
+ ///
+ public ulong PolyModulusDegree
+ {
+ get
+ {
+ NativeMethods.EncParams_GetPolyModulusDegree(NativePtr, out ulong result);
+ return result;
+ }
+ set
+ {
+ NativeMethods.EncParams_SetPolyModulusDegree(NativePtr, value);
+ }
+ }
+
+ ///
+ /// Get a copy of the currently set coefficient modulus parameter, or
+ /// set the coefficient modulus parameter.
+ ///
+ ///
+ /// When setting:
+ /// Sets the coefficient modulus parameter. The coefficient modulus consists of a list
+ /// of distinct prime numbers, and is represented by a list of
+ /// objects. The coefficient modulus directly affects the size of ciphertext elements,
+ /// the amount of computation that the scheme can perform (bigger is better), and the
+ /// security level (bigger is worse). In Microsoft SEAL each of the prime numbers in
+ /// the coefficient modulus must be at most 60 bits, and must be congruent to 1 modulo
+ /// 2*PolyModulusDegree.
+ ///
+ /// if the value being set is null
+ /// if the value being set is invalid
+ public IEnumerable CoeffModulus
+ {
+ get
+ {
+ ulong length = 0;
+ NativeMethods.EncParams_GetCoeffModulus(NativePtr, ref length, null);
+
+ IntPtr[] coeffArray = new IntPtr[length];
+ NativeMethods.EncParams_GetCoeffModulus(NativePtr, ref length, coeffArray);
+
+ List result = new List(checked((int)length));
+ foreach(IntPtr sm in coeffArray)
+ {
+ result.Add(new Modulus(sm));
+ }
+
+ return result;
+ }
+
+ set
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ IntPtr[] coeffArray = value.Select(sm => sm.NativePtr).ToArray();
+ NativeMethods.EncParams_SetCoeffModulus(NativePtr, (ulong)coeffArray.LongLength, coeffArray);
+ }
+ }
+
+ ///
+ /// Get a copy of the currently set plaintext modulus parameter, or
+ /// set the plaintext modulus parameter.
+ ///
+ ///
+ /// When setting:
+ /// Sets the plaintext modulus parameter. The plaintext modulus is an integer modulus
+ /// represented by the class. The plaintext modulus determines
+ /// the largest coefficient that plaintext polynomials can represent. It also affects the
+ /// amount of computation that the scheme can perform (bigger is worse). In Microsoft SEAL
+ /// the plaintext modulus can be at most 60 bits long, but can otherwise be any integer.
+ /// Note, however, that some features (e.g. batching) require the plaintext modulus to be
+ /// of a particular form.
+ ///
+ /// if the value being set is null
+ /// if scheme is not SchemeType.BFV
+ public Modulus PlainModulus
+ {
+ get
+ {
+ NativeMethods.EncParams_GetPlainModulus(NativePtr, out IntPtr ptr);
+ Modulus sm = new Modulus(ptr, owned: false);
+ return sm;
+ }
+ set
+ {
+ NativeMethods.EncParams_SetPlainModulus(NativePtr, value.NativePtr);
+ }
+ }
+
+ ///
+ /// Sets the plaintext modulus parameter.
+ ///
+ ///
+ /// Sets the plaintext modulus parameter. The plaintext modulus is an integer modulus
+ /// represented by the class. This method instead takes
+ /// a ulong and automatically creates the Modulus object. The plaintext modulus
+ /// determines the largest coefficient that plaintext polynomials can represent. It also
+ /// affects the amount of computation that the scheme can perform (bigger is worse). In
+ /// Microsoft SEAL the plaintext modulus can be at most 60 bits long, but can otherwise
+ /// be any integer. Note, however, that some features (e.g. batching) require the
+ /// plaintext modulus to be of a particular form.
+ ///
+ /// The new plaintext modulus
+ /// if scheme is not CKKS
+ public void SetPlainModulus(ulong plainModulus)
+ {
+ NativeMethods.EncParams_SetPlainModulus(NativePtr, plainModulus);
+ }
+
+ ///
+ /// Returns the encryption scheme type.
+ ///
+ public SchemeType Scheme
+ {
+ get
+ {
+ NativeMethods.EncParams_GetScheme(NativePtr, out byte scheme);
+ return (SchemeType)scheme;
+ }
+ }
+
+ ///
+ /// Returns an upper bound on the size of the EncryptionParameters, as if
+ /// it was written to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.EncParams_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the EncryptionParameters to an output stream.
+ ///
+ /// Saves the EncryptionParameters to an output stream. The output is in
+ /// binary format and not human-readable.
+ ///
+ /// The stream to save the EncryptionParameters to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.EncParams_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ ///
+ /// Loads an EncryptionParameters from an input stream overwriting the
+ /// current EncryptionParameters.
+ ///
+ /// The stream to load the EncryptionParameters from
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long Load(Stream stream)
+ {
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.EncParams_Load(NativePtr, outptr, size,
+ out outBytes),
+ stream);
+ }
+
+ ///
+ /// Returns the ParmsId of the current parameters. This function is intended
+ /// for internal use.
+ ///
+ internal ParmsId ParmsId
+ {
+ get
+ {
+ ParmsId id = new ParmsId();
+ NativeMethods.EncParams_GetParmsId(NativePtr, id.Block);
+ return id;
+ }
+ }
+
+ ///
+ /// Compares a given set of encryption parameters to the current set of
+ /// encryption parameters.
+ ///
+ ///
+ /// Compares a given set of encryption parameters to the current set of encryption
+ /// parameters. The comparison is performed by comparing hash blocks of the parameter
+ /// sets rather than comparing the parameters individually.
+ ///
+ /// The EncryptionParameters to compare against
+ public override bool Equals(object obj)
+ {
+ EncryptionParameters encParams = obj as EncryptionParameters;
+ return Equals(encParams);
+ }
+
+ ///
+ /// Returns a hash-code based on the EncryptionParameters.
+ ///
+ public override int GetHashCode()
+ {
+ return Utilities.ComputeArrayHashCode(ParmsId.Block);
+ }
+
+ #region IEquatable methods
+
+ ///
+ /// Compares a given set of encryption parameters to the current set of
+ /// encryption parameters.
+ ///
+ ///
+ ///
+ /// Compares a given set of encryption parameters to the current set of encryption
+ /// parameters. The comparison is performed by comparing hash blocks of the parameter
+ /// sets rather than comparing the parameters individually.
+ ///
+ /// The EncryptionParameters to compare against
+ public bool Equals(EncryptionParameters other)
+ {
+ if (null == other)
+ return false;
+
+ NativeMethods.EncParams_Equals(NativePtr, other.NativePtr, out bool result);
+ return result;
+ }
+
+ #endregion
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.EncParams_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/Encryptor.cs b/bigpiseal3.5.1/dotnet/src/Encryptor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fd4aba54af8f4c9c586dc01e89082ea2578fa409
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Encryptor.cs
@@ -0,0 +1,484 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Encrypts Plaintext objects into Ciphertext objects.
+ ///
+ ///
+ ///
+ /// Encrypts Plaintext objects into Ciphertext objects. Constructing an Encryptor
+ /// requires a SEALContext with valid encryption parameters, the public key and/or
+ /// the secret key. If an Encrytor is given a secret key, it supports symmetric-key
+ /// encryption. If an Encryptor is given a public key, it supports asymmetric-key
+ /// encryption.
+ ///
+ ///
+ /// Overloads
+ /// For the encrypt function we provide two overloads concerning the memory pool used in
+ /// allocations needed during the operation. In one overload the global memory pool is used
+ /// for this purpose, and in another overload the user can supply a MemoryPoolHandle
+ /// to to be used instead. This is to allow one single Encryptor to be used concurrently by
+ /// several threads without running into thread contention in allocations taking place during
+ /// operations. For example, one can share one single Encryptor across any number of threads,
+ /// but in each thread call the encrypt function by giving it a thread-local MemoryPoolHandle
+ /// to use. It is important for a developer to understand how this works to avoid unnecessary
+ /// performance bottlenecks.
+ ///
+ ///
+ /// NTT form
+ /// When using the BFV scheme (SchemeType.BFV), all plaintext and ciphertexts should
+ /// remain by default in the usual coefficient representation, i.e. not in NTT form.
+ /// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts
+ /// should remain by default in NTT form. We call these scheme-specific NTT states the
+ /// "default NTT form". Decryption requires the input ciphertexts to be in the default
+ /// NTT form, and will throw an exception if this is not the case.
+ ///
+ ///
+ public class Encryptor : NativeObject
+ {
+ ///
+ /// Creates an Encryptor instance initialized with the specified SEALContext,
+ /// public key, and/or secret key.
+ ///
+ /// The SEALContext
+ /// The public key
+ /// The secret key
+ /// if context is null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if publicKey is not valid
+ /// if secretKey is not null and not valid
+ public Encryptor(SEALContext context, PublicKey publicKey, SecretKey secretKey = null)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+ if (!ValCheck.IsValidFor(publicKey, context))
+ throw new ArgumentException("Public key is not valid for encryption parameters");
+
+ if (null == secretKey)
+ {
+ NativeMethods.Encryptor_Create(
+ context.NativePtr, publicKey.NativePtr, IntPtr.Zero, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+ else
+ {
+ if (!ValCheck.IsValidFor(secretKey, context))
+ throw new ArgumentException("Secret key is not valid for encryption parameters");
+ NativeMethods.Encryptor_Create(
+ context.NativePtr, publicKey.NativePtr, secretKey.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+ }
+
+ ///
+ /// Creates an Encryptor instance initialized with the specified SEALContext
+ /// and secret key.
+ ///
+ /// The SEALContext
+ /// The secret key
+ /// if context is null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ /// if secretKey is not valid
+ public Encryptor(SEALContext context, SecretKey secretKey)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+ if (!ValCheck.IsValidFor(secretKey, context))
+ throw new ArgumentException("Secret key is not valid for encryption parameters");
+
+ NativeMethods.Encryptor_Create(context.NativePtr, IntPtr.Zero, secretKey.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Give a new instance of public key.
+ ///
+ /// The public key
+ /// if publicKey is not valid
+ public void SetPublicKey(PublicKey publicKey)
+ {
+ NativeMethods.Encryptor_SetPublicKey(NativePtr, publicKey.NativePtr);
+ }
+
+ ///
+ /// Give a new instance of secret key.
+ ///
+ /// The secret key
+ /// if secretKey is not valid
+ public void SetSecretKey(SecretKey secretKey)
+ {
+ NativeMethods.Encryptor_SetSecretKey(NativePtr, secretKey.NativePtr);
+ }
+
+ ///
+ /// Encrypts a plaintext with the public key and stores the result in destination.
+ ///
+ ///
+ ///
+ /// Encrypts a plaintext with the public key and stores the result in destination.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to:
+ /// 1) in BFV, the highest (data) level in the modulus switching chain,
+ /// 2) in CKKS, the encryption parameters of the plaintext.
+ /// Dynamic memory allocations in the process are allocated from the memory
+ /// pool pointed to by the given MemoryPoolHandle.
+ ///
+ ///
+ /// The plaintext to encrypt
+ /// The ciphertext to overwrite with the encrypted
+ /// plaintext
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain or destination
+ /// are null
+ /// if a public key is not
+ /// set
+ /// if plain is not valid for the
+ /// encryption parameters
+ /// if plain is not in default NTT
+ /// form
+ /// if pool is uninitialized
+ public void Encrypt(
+ Plaintext plain, Ciphertext destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Encryptor_Encrypt(
+ NativePtr, plain.NativePtr, destination.NativePtr, poolHandle);
+ }
+
+ ///
+ /// Encrypts a zero plaintext with the public key and stores the result in
+ /// destination.
+ ///
+ ///
+ ///
+ /// Encrypts a zero plaintext with the public key and stores the result in
+ /// destination.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to
+ /// the given ParmsId. Dynamic memory allocations in the process are allocated
+ /// from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ ///
+ /// The ParmsId for the resulting ciphertext
+ /// The ciphertext to overwrite with the encrypted
+ /// plaintext
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either parmsId or destination are
+ /// null
+ /// if a public key is not set
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void EncryptZero(
+ ParmsId parmsId, Ciphertext destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Encryptor_EncryptZero1(
+ NativePtr, parmsId.Block, destination.NativePtr, poolHandle);
+ }
+
+ ///
+ /// Encrypts a zero plaintext with the public key and stores the result in
+ /// destination.
+ ///
+ ///
+ ///
+ /// Encrypts a zero plaintext with the public key and stores the result in
+ /// destination.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to the
+ /// highest (data) level in the modulus switching chain. Dynamic memory allocations
+ /// in the process are allocated from the memory pool pointed to by the given
+ /// MemoryPoolHandle.
+ ///
+ ///
+ /// The ciphertext to overwrite with the encrypted
+ /// plaintext
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if destination is null
+ /// if a public key is not set
+ /// if pool is uninitialized
+ public void EncryptZero(Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Encryptor_EncryptZero2(NativePtr, destination.NativePtr, poolHandle);
+ }
+
+ ///
+ /// Encrypts a plaintext with the secret key and stores the result in destination.
+ ///
+ ///
+ ///
+ /// Encrypts a plaintext with the secret key and stores the result in destination.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to:
+ /// 1) in BFV, the highest (data) level in the modulus switching chain,
+ /// 2) in CKKS, the encryption parameters of the plaintext.
+ /// Dynamic memory allocations in the process are allocated from the memory
+ /// pool pointed to by the given MemoryPoolHandle.
+ ///
+ ///
+ /// The plaintext to encrypt
+ /// The ciphertext to overwrite with the encrypted
+ /// plaintext
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain or destination are
+ /// null
+ /// if a secret key is not set
+ /// if plain is not valid for the encryption
+ /// parameters
+ /// if plain is not in default NTT form
+ /// if pool is uninitialized
+ public void EncryptSymmetric(
+ Plaintext plain, Ciphertext destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Encryptor_EncryptSymmetric(
+ NativePtr, plain.NativePtr, false, destination.NativePtr, poolHandle);
+ }
+
+ ///
+ /// Encrypts a zero plaintext with the secret key and stores the result in
+ /// destination.
+ ///
+ ///
+ ///
+ /// Encrypts a zero plaintext with the secret key and stores the result in
+ /// destination.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to the given
+ /// ParmsId. Dynamic memory allocations in the process are allocated from the
+ /// memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ ///
+ /// The ParmsId for the resulting ciphertext
+ /// The ciphertext to overwrite with the encrypted
+ /// plaintext
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either parmsId or destination are
+ /// null
+ /// if a secret key is not set
+ /// if parmsId is not valid for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void EncryptZeroSymmetric(
+ ParmsId parmsId, Ciphertext destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Encryptor_EncryptZeroSymmetric1(
+ NativePtr, parmsId.Block, false, destination.NativePtr, poolHandle);
+ }
+
+ ///
+ /// Encrypts a zero plaintext with the secret key and stores the result in
+ /// destination.
+ ///
+ ///
+ ///
+ /// Encrypts a zero plaintext with the secret key and stores the result in
+ /// destination.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to the
+ /// highest (data) level in the modulus switching chain. Dynamic memory allocations
+ /// in the process are allocated from the memory pool pointed to by the given
+ /// MemoryPoolHandle.
+ ///
+ ///
+ /// The ciphertext to overwrite with the encrypted
+ /// plaintext
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if destination is null
+ /// if a secret key is not set
+ /// if pool is uninitialized
+ public void EncryptZeroSymmetric(
+ Ciphertext destination,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Encryptor_EncryptZeroSymmetric2(
+ NativePtr, false, destination.NativePtr, poolHandle);
+ }
+
+ ///
+ /// Encrypts a plaintext with the secret key and returns the ciphertext as
+ /// a serializable object.
+ ///
+ ///
+ ///
+ /// Encrypts a plaintext with the secret key and returns the ciphertext as
+ /// a serializable object.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to:
+ /// 1) in BFV, the highest (data) level in the modulus switching chain,
+ /// 2) in CKKS, the encryption parameters of the plaintext.
+ /// Dynamic memory allocations in the process are allocated from the memory
+ /// pool pointed to by the given MemoryPoolHandle.
+ ///
+ ///
+ /// Half of the ciphertext data is pseudo-randomly generated from a seed to
+ /// reduce the object size. The resulting serializable object cannot be used
+ /// directly and is meant to be serialized for the size reduction to have an
+ /// impact.
+ ///
+ ///
+ /// The plaintext to encrypt
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if plain is null
+ /// if a secret key is not set
+ /// if plain is not valid for the encryption
+ /// parameters
+ /// if plain is not in default NTT
+ /// form
+ /// if pool is uninitialized
+ public Serializable EncryptSymmetric(
+ Plaintext plain,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ Ciphertext destination = new Ciphertext();
+ NativeMethods.Encryptor_EncryptSymmetric(
+ NativePtr, plain.NativePtr, true, destination.NativePtr, poolHandle);
+ return new Serializable(destination);
+ }
+
+ ///
+ /// Encrypts a zero plaintext with the secret key and returns the ciphertext
+ /// as a serializable object.
+ ///
+ ///
+ ///
+ /// Encrypts a zero plaintext with the secret key and returns the ciphertext
+ /// as a serializable object.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to
+ /// the given ParmsId. Dynamic memory allocations in the process are allocated
+ /// from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ ///
+ /// Half of the ciphertext data is pseudo-randomly generated from a seed to
+ /// reduce the object size. The resulting serializable object cannot be used
+ /// directly and is meant to be serialized for the size reduction to have an
+ /// impact.
+ ///
+ ///
+ /// The ParmsId for the resulting ciphertext
+ /// The MemoryPoolHandle pointing to a valid memory
+ /// pool
+ /// if parmsId is null
+ /// if a secret key is not
+ /// set
+ /// if parmsId is not valid for the
+ /// encryption parameters
+ /// if pool is uninitialized
+ public Serializable EncryptZeroSymmetric(
+ ParmsId parmsId,
+ MemoryPoolHandle pool = null)
+ {
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ Ciphertext destination = new Ciphertext();
+ NativeMethods.Encryptor_EncryptZeroSymmetric1(
+ NativePtr, parmsId.Block, true, destination.NativePtr, poolHandle);
+ return new Serializable(destination);
+ }
+
+ ///
+ /// Encrypts a zero plaintext with the secret key and returns the ciphertext
+ /// as a serializable object.
+ ///
+ ///
+ ///
+ /// Encrypts a zero plaintext with the secret key and returns the ciphertext
+ /// as a serializable object.
+ ///
+ ///
+ /// The encryption parameters for the resulting ciphertext correspond to the
+ /// highest (data) level in the modulus switching chain. Dynamic memory
+ /// allocations in the process are allocated from the memory pool pointed to
+ /// by the given MemoryPoolHandle.
+ ///
+ ///
+ /// Half of the ciphertext data is pseudo-randomly generated from a seed to
+ /// reduce the object size. The resulting serializable object cannot be used
+ /// directly and is meant to be serialized for the size reduction to have an
+ /// impact.
+ ///
+ ///
+ /// The MemoryPoolHandle pointing to a valid memory
+ /// pool
+ /// if a secret key is not
+ /// set
+ /// if pool is uninitialized
+ public Serializable EncryptZeroSymmetric(MemoryPoolHandle pool = null)
+ {
+ IntPtr poolHandle = pool?.NativePtr ?? IntPtr.Zero;
+ Ciphertext destination = new Ciphertext();
+ NativeMethods.Encryptor_EncryptZeroSymmetric2(
+ NativePtr, true, destination.NativePtr, poolHandle);
+ return new Serializable(destination);
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.Encryptor_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/Evaluator.cs b/bigpiseal3.5.1/dotnet/src/Evaluator.cs
new file mode 100644
index 0000000000000000000000000000000000000000..84a53ce33c3f0c87f6dcd4a447933952a6c2c985
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Evaluator.cs
@@ -0,0 +1,1628 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Provides operations on ciphertexts.
+ ///
+ ///
+ ///
+ ///
+ /// Provides operations on ciphertexts. Due to the properties of the encryption scheme,
+ /// the arithmetic operations pass through the encryption layer to the underlying plaintext,
+ /// changing it according to the type of the operation. Since the plaintext elements are
+ /// fundamentally polynomials in the polynomial quotient ring Z_T[x]/(X^N+1), where T is
+ /// the plaintext modulus and X^N+1 is the polynomial modulus, this is the ring where the
+ /// arithmetic operations will take place. BatchEncoder (batching) provider an alternative
+ /// possibly more convenient view of the plaintext elements as 2-by-(N2/2) matrices of
+ /// integers modulo the plaintext modulus. In the batching view the arithmetic operations
+ /// act on the matrices element-wise. Some of the operations only apply in the batching
+ /// view, such as matrix row and column rotations. Other operations such as relinearization
+ /// have no semantic meaning but are necessary for performance reasons.
+ ///
+ ///
+ /// Arithmetic Operations
+ /// The core operations are arithmetic operations, in particular multiplication and addition
+ /// of ciphertexts. In addition to these, we also provide negation, subtraction, squaring,
+ /// exponentiation, and multiplication and addition of several ciphertexts for convenience.
+ /// in many cases some of the inputs to a computation are plaintext elements rather than
+ /// ciphertexts. For this we provide fast "plain" operations: plain addition, plain subtraction,
+ /// and plain multiplication.
+ ///
+ ///
+ /// Relinearization
+ /// One of the most important non-arithmetic operations is relinearization, which takes
+ /// as input a ciphertext of size K+1 and relinearization keys (at least K-1 keys are needed),
+ /// and changes the size of the ciphertext down to 2 (minimum size). For most use-cases only
+ /// one relinearization key suffices, in which case relinearization should be performed after
+ /// every multiplication. Homomorphic multiplication of ciphertexts of size K+1 and L+1
+ /// outputs a ciphertext of size K+L+1, and the computational cost of multiplication is
+ /// proportional to K*L. Plain multiplication and addition operations of any type do not
+ /// change the size. Relinearization requires relinearization keys to have been generated.
+ ///
+ ///
+ /// Rotations
+ /// When batching is enabled, we provide operations for rotating the plaintext matrix rows
+ /// cyclically left or right, and for rotating the columns (swapping the rows). Rotations
+ /// require Galois keys to have been generated.
+ ///
+ ///
+ /// Other Operations
+ /// We also provide operations for transforming ciphertexts to NTT form and back, and for
+ /// transforming plaintext polynomials to NTT form. These can be used in a very fast plain
+ /// multiplication variant, that assumes the inputs to be in NTT form. Since the NTT has to
+ /// be done in any case in plain multiplication, this function can be used when e.g. one
+ /// plaintext input is used in several plain multiplication, and transforming it several
+ /// times would not make sense.
+ ///
+ ///
+ /// NTT form
+ /// When using the BFV scheme (SchemeType.BFV), all plaintexts and ciphertexts should
+ /// remain by default in the usual coefficient representation, i.e., not in NTT form.
+ /// When using the CKKS scheme (SchemeType.CKKS), all plaintexts and ciphertexts
+ /// should remain by default in NTT form. We call these scheme-specific NTT states the
+ /// "default NTT form". Some functions, such as add, work even if the inputs are not in
+ /// the default state, but others, such as multiply, will throw an exception. The output
+ /// of all evaluation functions will be in the same state as the input(s), with the
+ /// exception of the TransformToNTT and TransformFromNTT functions, which change the
+ /// state. Ideally, unless these two functions are called, all other functions should
+ /// "just work".
+ ///
+ ///
+ /// for more details on encryption parameters.
+ /// for more details on batching
+ /// for more details on relinearization keys.
+ /// for more details on Galois keys.
+ public class Evaluator : NativeObject
+ {
+ ///
+ /// Creates an Evaluator instance initialized with the specified SEALContext.
+ ///
+ ///
+ /// The SEALContext
+ /// if context is null
+ /// if the context is not set or encryption
+ /// parameters are not valid
+ public Evaluator(SEALContext context)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+
+ NativeMethods.Evaluator_Create(context.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Negates a ciphertext.
+ ///
+ ///
+ /// The ciphertext to negate
+ /// if encrypted is null
+ /// if encrypted is not valid for the encryption parameters
+ /// if result ciphertext is transparent
+ public void NegateInplace(Ciphertext encrypted)
+ {
+ Negate(encrypted, destination: encrypted);
+ }
+
+ ///
+ /// Negates a ciphertext and stores the result in the destination parameter.
+ ///
+ /// The ciphertext to negate
+ /// The ciphertext to overwrite with the negated result
+ /// if either encrypted or destionation are null
+ /// if encrypted is not valid for the encryption parameters
+ /// if result ciphertext is transparent
+ public void Negate(Ciphertext encrypted, Ciphertext destination)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_Negate(NativePtr, encrypted.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Adds two ciphertexts.
+ ///
+ ///
+ /// This function adds together encrypted1 and encrypted2 and stores the result in encrypted1.
+ ///
+ /// The first ciphertext to add
+ /// The second ciphertext to add
+ /// if either encrypted1 or encrypted2 are null
+ /// if encrypted1 or encrypted2 is not valid for
+ /// the encryption parameters
+ /// if encrypted1 and encrypted2 are in different
+ /// NTT forms
+ /// if encrypted1 and encrypted2 have different scale
+ /// if result ciphertext is transparent
+ public void AddInplace(Ciphertext encrypted1, Ciphertext encrypted2)
+ {
+ Add(encrypted1, encrypted2, destination: encrypted1);
+ }
+
+ ///
+ /// Adds two ciphertexts.
+ ///
+ ///
+ /// This function adds together encrypted1 and encrypted2 and stores the result in the destination
+ /// parameter.
+ ///
+ /// The first ciphertext to add
+ /// The second ciphertext to add
+ /// The ciphertext to overwrite with the addition result
+ /// if either encrypted1, encrypted2 or destination are null
+ /// if encrypted1 or encrypted2 is not valid for
+ /// the encryption parameters
+ /// if encrypted1 and encrypted2 are in different
+ /// NTT forms
+ /// if encrypted1 and encrypted2 have different scale
+ /// if result ciphertext is transparent
+ public void Add(Ciphertext encrypted1, Ciphertext encrypted2, Ciphertext destination)
+ {
+ if (null == encrypted1)
+ throw new ArgumentNullException(nameof(encrypted1));
+ if (null == encrypted2)
+ throw new ArgumentNullException(nameof(encrypted2));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_Add(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Adds together a vector of ciphertexts and stores the result in the destination
+ /// parameter.
+ ///
+ /// The ciphertexts to add
+ /// The ciphertext to overwrite with the addition result
+ /// if either encrypteds or destination are null
+ /// if encrypteds is empty
+ /// if the encrypteds are not valid for the encryption
+ /// parameters
+ /// if encrypteds are in different NTT forms
+ /// if encrypteds have different scale
+ /// if result ciphertext is transparent
+ public void AddMany(IEnumerable encrypteds, Ciphertext destination)
+ {
+ if (null == encrypteds)
+ throw new ArgumentNullException(nameof(encrypteds));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr[] encarray = encrypteds.Select(c => c.NativePtr).ToArray();
+ NativeMethods.Evaluator_AddMany(NativePtr, (ulong)encarray.Length, encarray, destination.NativePtr);
+ }
+
+ ///
+ /// Subtracts two ciphertexts.
+ ///
+ ///
+ /// This function computes the difference of encrypted1 and encrypted2, and stores the result in encrypted1.
+ ///
+ /// The ciphertext to subtract from
+ /// The ciphertext to subtract
+ /// if either encrypted1 or encrypted2 are null
+ /// if encrypted1 or encrypted2 is not valid for the
+ /// encryption parameters
+ /// if encrypted1 and encrypted2 are in different
+ /// NTT forms
+ /// if encrypted1 and encrypted2 have different scale
+ /// if result ciphertext is transparent
+ public void SubInplace(Ciphertext encrypted1, Ciphertext encrypted2)
+ {
+ Sub(encrypted1, encrypted2, destination: encrypted1);
+ }
+
+ ///
+ /// Subtracts two ciphertexts.
+ ///
+ /// This function computes the difference of encrypted1 and encrypted2 and stores the result
+ /// in the destination parameter.
+ ///
+ /// The ciphertext to subtract from
+ /// The ciphertext to subtract
+ /// The ciphertext to overwrite with the subtraction result
+ /// if either encrypted1, encrypted2 or destination are null
+ /// if encrypted1 or encrypted2 is not valid for the
+ /// encryption parameters
+ /// if encrypted1 and encrypted2 are in different
+ /// NTT forms
+ /// if encrypted1 and encrypted2 have different scale
+ /// if result ciphertext is transparent
+ public void Sub(Ciphertext encrypted1, Ciphertext encrypted2, Ciphertext destination)
+ {
+ if (null == encrypted1)
+ throw new ArgumentNullException(nameof(encrypted1));
+ if (null == encrypted2)
+ throw new ArgumentNullException(nameof(encrypted2));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_Sub(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Multiplies two ciphertexts.
+ ///
+ /// This functions computes the product of encrypted1 and encrypted2 and stores the
+ /// result in encrypted1. Dynamic memory allocations in the process are allocated from the
+ /// memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The first ciphertext to multiply
+ /// The second ciphertext to multiply
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted1, encrypted2 are null
+ /// if encrypted1 or encrypted2 is not valid for the
+ /// encryption parameters
+ /// if encrypted1 or encrypted2 is not in the default
+ /// NTT form
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void MultiplyInplace(Ciphertext encrypted1, Ciphertext encrypted2,
+ MemoryPoolHandle pool = null)
+ {
+ Multiply(encrypted1, encrypted2, destination: encrypted1, pool: pool);
+ }
+
+ ///
+ /// Multiplies two ciphertexts.
+ ///
+ ///
+ /// This functions computes the product of encrypted1 and encrypted2 and stores the result
+ /// in the destination parameter. Dynamic memory allocations in the process are allocated
+ /// from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The first ciphertext to multiply
+ /// The second ciphertext to multiply
+ /// The ciphertext to overwrite with the multiplication result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted1, encrypted2, destination are null
+ /// if encrypted1 or encrypted2 is not valid for the
+ /// encryption parameters
+ /// if encrypted1 or encrypted2 is not in the default
+ /// NTT form
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void Multiply(Ciphertext encrypted1, Ciphertext encrypted2,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted1)
+ throw new ArgumentNullException(nameof(encrypted1));
+ if (null == encrypted2)
+ throw new ArgumentNullException(nameof(encrypted2));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_Multiply(NativePtr, encrypted1.NativePtr, encrypted2.NativePtr, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Squares a ciphertext.
+ ///
+ ///
+ /// This functions computes the square of encrypted. Dynamic memory allocations in the process
+ /// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to square
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted are null
+ /// if encrypted is not valid for the encryption
+ /// parameters
+ /// if encrypted is not in the default NTT form
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void SquareInplace(Ciphertext encrypted, MemoryPoolHandle pool = null)
+ {
+ Square(encrypted, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Squares a ciphertext.
+ ///
+ ///
+ /// This functions computes the square of encrypted and stores the result in the destination
+ /// parameter. Dynamic memory allocations in the process are allocated from the memory pool
+ /// pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to square
+ /// The ciphertext to overwrite with the square
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, destination are null
+ /// if encrypted is not valid for the encryption
+ /// parameters
+ /// if encrypted is not in the default NTT form
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void Square(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_Square(NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Relinearizes a ciphertext.
+ ///
+ ///
+ /// This functions relinearizes encrypted, reducing its size down to 2. If the size
+ /// of encrypted is K+1, the given relinearization keys need to have size at least K-1.
+ /// Dynamic memory allocations in the process are allocated from the memory pool pointed
+ /// to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to relinearize
+ /// The relinearization keys
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, relinKeys are null
+ /// if encrypted or relinKeys is not valid for the
+ /// encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if relinKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if the size of relinKeys is too small
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void RelinearizeInplace(Ciphertext encrypted, RelinKeys relinKeys,
+ MemoryPoolHandle pool = null)
+ {
+ Relinearize(encrypted, relinKeys, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Relinearizes a ciphertext.
+ ///
+ ///
+ /// This functions relinearizes encrypted, reducing its size down to 2, and stores the
+ /// result in the destination parameter. If the size of encrypted is K+1, the given
+ /// relinearization keys need to have size at least K-1. Dynamic memory allocations in the
+ /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to relinearize
+ /// The relinearization keys
+ /// The ciphertext to overwrite with the relinearized result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, relinKeys or destination are null
+ /// if encrypted or relinKeys is not valid for the
+ /// encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if relinKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if the size of relinKeys is too small
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void Relinearize(Ciphertext encrypted, RelinKeys relinKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == relinKeys)
+ throw new ArgumentNullException(nameof(relinKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_Relinearize(
+ NativePtr, encrypted.NativePtr, relinKeys.NativePtr, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1} and stores the result in the destination parameter.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1} and stores the result in the destination parameter. Dynamic
+ /// memory allocations in the process are allocated from the memory pool pointed to by
+ /// the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The ciphertext to overwrite with the modulus switched result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or destination are null
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if encrypted is already at lowest level
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void ModSwitchToNext(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_ModSwitchToNext(
+ NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1}.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1}. Dynamic memory allocations in the process are allocated from
+ /// the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if encrypted is null
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if encrypted is already at lowest level
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void ModSwitchToNextInplace(Ciphertext encrypted, MemoryPoolHandle pool = null)
+ {
+ ModSwitchToNext(encrypted, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Modulus switches an NTT transformed plaintext from modulo q_1...q_k down to modulo
+ /// q_1...q_{k-1}.
+ ///
+ /// The plaintext to be switched to a smaller modulus
+ /// if plain is null
+ /// if plain is not in NTT form
+ /// if plain is not valid for the encryption parameters
+ /// if plain is already at lowest level
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ public void ModSwitchToNextInplace(Plaintext plain)
+ {
+ ModSwitchToNext(plain, destination: plain);
+ }
+
+ ///
+ /// Modulus switches an NTT transformed plaintext from modulo q_1...q_k down to modulo
+ /// q_1...q_{k-1} and stores the result in the destination parameter.
+ ///
+ /// The plaintext to be switched to a smaller modulus
+ /// destination The plaintext to overwrite with the modulus switched result
+ /// if either plain or destination are null
+ /// if plain is not in NTT form
+ /// if plain is not valid for the encryption parameters
+ /// if plain is already at lowest level
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ /// if pool is uninitialized
+ public void ModSwitchToNext(Plaintext plain, Plaintext destination)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_ModSwitchToNext(NativePtr, plain.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId. Dynamic memory allocations in
+ /// the process are allocated from the memory pool pointed to by the given
+ /// MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The target parmsId
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or parmsId are null
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if parmsId is not valid for the encryption parameters
+ /// if encrypted is already at lower level in modulus chain
+ /// than the parameters corresponding to parmsId
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void ModSwitchToInplace(Ciphertext encrypted, ParmsId parmsId, MemoryPoolHandle pool = null)
+ {
+ ModSwitchTo(encrypted, parmsId, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId and stores the result in the
+ /// destination parameter.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId and stores the result in the
+ /// destination parameter. Dynamic memory allocations in the process are allocated
+ /// from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The target parmsId
+ /// The ciphertext to overwrite with the modulus switched result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, parmsId or destination are null
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if parmsId is not valid for the encryption parameters
+ /// if encrypted is already at lower level in modulus chain
+ /// than the parameters corresponding to parmsId
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void ModSwitchTo(Ciphertext encrypted, ParmsId parmsId, Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_ModSwitchTo(
+ NativePtr, encrypted.NativePtr, parmsId.Block, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Given an NTT transformed plaintext modulo q_1...q_k, this function switches the
+ /// modulus down until the parameters reach the given ParmsId.
+ ///
+ /// The plaintext to be switched to a smaller modulus
+ /// The target parmsId
+ /// if either plain or parmsId is null
+ /// if plain is not in NTT form
+ /// if plain is not valid for the encryption parameters
+ /// if parmsId is not valid for the encryption parameters
+ /// if plain is already at lower level in modulus chain
+ /// than the parameters corresponding to parmsId
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ public void ModSwitchToInplace(Plaintext plain, ParmsId parmsId)
+ {
+ ModSwitchTo(plain, parmsId, destination: plain);
+ }
+
+ ///
+ /// Given an NTT transformed plaintext modulo q_1...q_k, this function switches the
+ /// modulus down until the parameters reach the given ParmsId and stores the result in
+ /// the destination parameter.
+ ///
+ /// The plaintext to be switched to a smaller modulus
+ /// The target parmsId
+ /// The plaintext to overwrite with the modulus switched result
+ /// if either plain, parmsId or destination are null
+ /// if plain is not in NTT form
+ /// if plain is not valid for the encryption parameters
+ /// if parmsId is not valid for the encryption parameters
+ /// if plain is already at lower level in modulus chain
+ /// than the parameters corresponding to parmsId
+ /// if, when using SchemeType.CKKS, the scale is too
+ /// large for the new encryption parameters
+ public void ModSwitchTo(Plaintext plain, ParmsId parmsId,
+ Plaintext destination)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_ModSwitchTo(NativePtr, plain.NativePtr, parmsId.Block, destination.NativePtr);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1}, scales the message down accordingly, and stores the
+ /// result in the destination parameter.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1}, scales the message down accordingly, and stores the
+ /// result in the destination parameter. Dynamic memory allocations in the process
+ /// are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The ciphertext to overwrite with the modulus switched result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or destination are null
+ /// if the scheme is invalid for rescaling
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if encrypted is already at lowest level
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void RescaleToNext(Ciphertext encrypted, Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_RescaleToNext(
+ NativePtr, encrypted.NativePtr, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1} and scales the message down accordingly.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down to q_1...q_{k-1} and scales the message down accordingly. Dynamic memory
+ /// allocations in the process are allocated from the memory pool pointed to by the
+ /// given MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if encrypted is null
+ /// if the scheme is invalid for rescaling
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// guaranteed to be
+ /// if encrypted is already at lowest level
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void RescaleToNextInplace(Ciphertext encrypted, MemoryPoolHandle pool = null)
+ {
+ RescaleToNext(encrypted, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId and scales the message down
+ /// accordingly.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId and scales the message down
+ /// accordingly. Dynamic memory allocations in the process are allocated from the
+ /// memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The target parmsId
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or parmsId are null
+ /// if the scheme is invalid for rescaling
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if parmsId is not valid for the encryption parameters
+ /// if encrypted is already at lower level in modulus chain
+ /// than the parameters corresponding to parmsId
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void RescaleToInplace(Ciphertext encrypted, ParmsId parmsId, MemoryPoolHandle pool = null)
+ {
+ RescaleTo(encrypted, parmsId, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId, scales the message down
+ /// accordingly, and stores the result in the destination parameter.
+ ///
+ ///
+ /// Given a ciphertext encrypted modulo q_1...q_k, this function switches the modulus
+ /// down until the parameters reach the given ParmsId, scales the message down
+ /// accordingly, and stores the result in the destination parameter. Dynamic memory
+ /// allocations in the process are allocated from the memory pool pointed to by the
+ /// given MemoryPoolHandle.
+ ///
+ /// The ciphertext to be switched to a smaller modulus
+ /// The target parmsId
+ /// The ciphertext to overwrite with the modulus switched result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, parmsId or destination are null.
+ /// if the scheme is invalid for rescaling
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if parmsId is not valid for the encryption parameters
+ /// if encrypted is already at lower level in modulus chain
+ /// than the parameters corresponding to parmsId
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void RescaleTo(Ciphertext encrypted, ParmsId parmsId, Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_RescaleTo(
+ NativePtr, encrypted.NativePtr, parmsId.Block, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Multiplies several ciphertexts together. This function computes the product of several
+ /// ciphertext given as an IEnumerable and stores the result in the destination parameter.
+ ///
+ ///
+ /// Multiplies several ciphertexts together. This function computes the product of several
+ /// ciphertext given as an IEnumerable and stores the result in the destination parameter.
+ /// The multiplication is done in a depth-optimal order, and relinearization is performed
+ /// automatically after every multiplication in the process. In relinearization the given
+ /// relinearization keys are used. Dynamic memory allocations in the process are allocated
+ /// from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertexts to multiply
+ /// The relinearization keys
+ /// The ciphertext to overwrite with the multiplication result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypteds, relinKeys or destination are null
+ /// if scheme is not SchemeType.BFV
+ /// if encrypteds is empty
+ /// if the ciphertexts or relinKeys are not valid for
+ /// the encryption parameters
+ /// if encrypteds are not in the default NTT form
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if the size of relinKeys is too small
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void MultiplyMany(IEnumerable encrypteds, RelinKeys relinKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypteds)
+ throw new ArgumentNullException(nameof(encrypteds));
+ if (null == relinKeys)
+ throw new ArgumentNullException(nameof(relinKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr[] encarray = encrypteds.Select(c => c.NativePtr).ToArray();
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_MultiplyMany(
+ NativePtr, (ulong)encarray.Length, encarray, relinKeys.NativePtr,
+ destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Exponentiates a ciphertext.
+ ///
+ ///
+ /// This functions raises encrypted to a power. Dynamic memory allocations in the process
+ /// are allocated from the memory pool pointed to by the given MemoryPoolHandle. The
+ /// exponentiation is done in a depth-optimal order, and relinearization is performed
+ /// automatically after every multiplication in the process. In relinearization the given
+ /// relinearization keys are used.
+ ///
+ /// The ciphertext to exponentiate
+ /// The power to raise the ciphertext to
+ /// The relinearization keys
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or relinKeys are null
+ /// if scheme is not SchemeType.BFV
+ /// if encrypted or relinKeys is not valid for the
+ /// encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if exponent is zero
+ /// if the size of relinKeys is too small
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void ExponentiateInplace(Ciphertext encrypted, ulong exponent,
+ RelinKeys relinKeys, MemoryPoolHandle pool = null)
+ {
+ Exponentiate(encrypted, exponent, relinKeys, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Exponentiates a ciphertext.
+ ///
+ ///
+ /// This functions raises encrypted to a power and stores the result in the destination
+ /// parameter. Dynamic memory allocations in the process are allocated from the memory pool
+ /// pointed to by the given MemoryPoolHandle. The exponentiation is done in a depth-optimal
+ /// order, and relinearization is performed automatically after every multiplication in the
+ /// process. In relinearization the given relinearization keys are used.
+ ///
+ /// The ciphertext to exponentiate
+ /// The power to raise the ciphertext to
+ /// The relinearization keys
+ /// The ciphertext to overwrite with the power
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if scheme is not SchemeType.BFV
+ /// if encrypted or relinKeys is not valid for the
+ /// encryption parameters
+ /// if encrypted is not in the default NTT form
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if exponent is zero
+ /// if the size of relinKeys is too small
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void Exponentiate(Ciphertext encrypted, ulong exponent, RelinKeys relinKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == relinKeys)
+ throw new ArgumentNullException(nameof(relinKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_Exponentiate(
+ NativePtr, encrypted.NativePtr, exponent, relinKeys.NativePtr,
+ destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Adds a ciphertext and a plaintext.
+ ///
+ ///
+ /// Adds a ciphertext and a plaintext. The plaintext must be valid for the current
+ /// encryption parameters.
+ ///
+ /// The ciphertext to add
+ /// The plaintext to add
+ /// if either encrypted or plain are null
+ /// if encrypted or plain is not valid for the encryption
+ /// parameters
+ /// if encrypted or plain is in NTT form
+ /// if result ciphertext is transparent
+ public void AddPlainInplace(Ciphertext encrypted, Plaintext plain)
+ {
+ AddPlain(encrypted, plain, destination: encrypted);
+ }
+
+ ///
+ /// Adds a ciphertext and a plaintext.
+ ///
+ ///
+ /// Adds a ciphertext and a plaintext. This function adds a ciphertext and a plaintext
+ /// and stores the result in the destination parameter. The plaintext must be valid for
+ /// the current encryption parameters.
+ ///
+ /// The ciphertext to add
+ /// The plaintext to add
+ /// The ciphertext to overwrite with the addition result
+ /// if either encrypted, plain or destination are null
+ /// if encrypted or plain is not valid for the encryption
+ /// parameters
+ /// if encrypted or plain is in NTT form
+ /// if result ciphertext is transparent
+ public void AddPlain(Ciphertext encrypted, Plaintext plain, Ciphertext destination)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_AddPlain(
+ NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Subtracts a plaintext from a ciphertext.
+ ///
+ ///
+ /// Subtracts a plaintext from a ciphertext. The plaintext must be valid for the current
+ /// encryption parameters.
+ ///
+ /// The ciphertext to subtract from
+ /// The plaintext to subtract
+ /// if either encrypted or plain are null
+ /// if encrypted or plain is not valid for the encryption
+ /// parameters
+ /// if encrypted or plain is in NTT form
+ /// if result ciphertext is transparent
+ public void SubPlainInplace(Ciphertext encrypted, Plaintext plain)
+ {
+ SubPlain(encrypted, plain, destination: encrypted);
+ }
+
+ ///
+ /// Subtracts a plaintext from a ciphertext.
+ ///
+ /// This function subtracts a plaintext from a ciphertext and stores the result in the
+ /// destination parameter. The plaintext must be valid for the current encryption parameters.
+ ///
+ /// The ciphertext to subtract from
+ /// The plaintext to subtract
+ /// The ciphertext to overwrite with the subtraction result
+ /// if either encrypted, plain or destination are null
+ /// if encrypted or plain is not valid for the encryption
+ /// parameters
+ /// if encrypted or plain is in NTT form
+ /// if result ciphertext is transparent
+ public void SubPlain(Ciphertext encrypted, Plaintext plain, Ciphertext destination)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_SubPlain(
+ NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Multiplies a ciphertext with a plaintext.
+ ///
+ /// Multiplies a ciphertext with a plaintext. The plaintext must be valid for the
+ /// current encryption parameters, and cannot be identially 0. Dynamic memory allocations in
+ /// the process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to multiply
+ /// The plaintext to multiply
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or plain are null.
+ /// if the encrypted or plain is not valid for the encryption
+ /// parameters
+ /// if encrypted and plain are in different NTT forms
+ /// if plain is zero
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void MultiplyPlainInplace(Ciphertext encrypted, Plaintext plain, MemoryPoolHandle pool = null)
+ {
+ MultiplyPlain(encrypted, plain, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Multiplies a ciphertext with a plaintext.
+ ///
+ ///
+ /// This function multiplies a ciphertext with a plaintext and stores the result in the
+ /// destination parameter. The plaintext must be valid for the current encryption parameters,
+ /// and cannot be identially 0. Dynamic memory allocations in the process are allocated from
+ /// the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to multiply
+ /// The plaintext to multiply
+ /// The ciphertext to overwrite with the multiplication result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, plain or destination are null
+ /// if the encrypted or plain is not valid for the
+ /// encryption parameters
+ /// if encrypted and plain are in different NTT forms
+ /// if plain is zero
+ /// if, when using SchemeType.CKKS, the output scale
+ /// is too large for the encryption parameters
+ /// if pool is uninitialized
+ /// if result ciphertext is transparent
+ public void MultiplyPlain(Ciphertext encrypted, Plaintext plain,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_MultiplyPlain(
+ NativePtr, encrypted.NativePtr, plain.NativePtr, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Transforms a plaintext to NTT domain.
+ ///
+ /// This functions applies the Number Theoretic Transform to a plaintext by first
+ /// embedding integers modulo the plaintext modulus to integers modulo the coefficient
+ /// modulus and then performing David Harvey's NTT on the resulting polynomial. The
+ /// transformation is done with respect to encryption parameters corresponding to a given
+ /// parmsId. For the operation to be valid, the plaintext must have degree less than
+ /// PolyModulusDegree and each coefficient must be less than the plaintext modulus, i.e.,
+ /// the plaintext must be a valid plaintext under the current encryption parameters.
+ /// Dynamic memory allocations in the process are allocated from the memory pool pointed
+ /// to by the given MemoryPoolHandle.
+ ///
+ /// The plaintext to transform
+ /// The ParmsId with respect to which the NTT is done
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain or parmsId are null
+ /// if plain is already in NTT form
+ /// if plain or parmsId is not valid for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void TransformToNTTInplace(Plaintext plain, ParmsId parmsId, MemoryPoolHandle pool = null)
+ {
+ TransformToNTT(plain, parmsId, destinationNTT: plain, pool: pool);
+ }
+
+ ///
+ /// Transforms a plaintext to NTT domain.
+ ///
+ ///
+ /// This functions applies the Number Theoretic Transform to a plaintext by first
+ /// embedding integers modulo the plaintext modulus to integers modulo the coefficient
+ /// modulus and then performing David Harvey's NTT on the resulting polynomial. The
+ /// transformation is done with respect to encryption parameters corresponding to
+ /// a given ParmsId. The result is stored in the destinationNTT parameter. For the
+ /// operation to be valid, the plaintext must have degree less than PolyModulusDegree
+ /// and each coefficient must be less than the plaintext modulus, i.e., the plaintext
+ /// must be a valid plaintext under the current encryption parameters. Dynamic memory
+ /// allocations in the process are allocated from the memory pool pointed to by the
+ /// given MemoryPoolHandle.
+ ///
+ /// The plaintext to transform
+ /// The ParmsId with respect to which the NTT is done
+ /// The plaintext to overwrite with the transformed result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either plain, parmsId or destinationNTT are null
+ /// if plain is already in NTT form
+ /// if plain or parmsId is not valid for the encryption
+ /// parameters
+ /// if pool is uninitialized
+ public void TransformToNTT(Plaintext plain, ParmsId parmsId,
+ Plaintext destinationNTT, MemoryPoolHandle pool = null)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+ if (null == destinationNTT)
+ throw new ArgumentNullException(nameof(destinationNTT));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_TransformToNTT(NativePtr, plain.NativePtr, parmsId.Block, destinationNTT.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Transforms a ciphertext to NTT domain.
+ ///
+ ///
+ /// Transforms a ciphertext to NTT domain. This functions applies David Harvey's Number
+ /// Theoretic Transform separately to each polynomial of a ciphertext.
+ ///
+ /// The ciphertext to transform
+ /// if encrypted is null
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is already in NTT form
+ /// if result ciphertext is transparent
+ public void TransformToNTTInplace(Ciphertext encrypted)
+ {
+ TransformToNTT(encrypted, destinationNTT: encrypted);
+ }
+
+ ///
+ /// Transforms a ciphertext to NTT domain.
+ ///
+ ///
+ /// Transforms a ciphertext to NTT domain. This functions applies David Harvey's Number
+ /// Theoretic Transform separately to each polynomial of a ciphertext. The result is
+ /// stored in the DestinationNTT parameter.
+ ///
+ /// The ciphertext to transform
+ /// The ciphertext to overwrite with the transformed result
+ /// if either encrypted or destinationNTT are null
+ /// if encrypted is not valid for the encryption parameters
+ /// if encrypted is already in NTT form
+ /// if result ciphertext is transparent
+ public void TransformToNTT(Ciphertext encrypted,
+ Ciphertext destinationNTT)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == destinationNTT)
+ throw new ArgumentNullException(nameof(destinationNTT));
+
+ NativeMethods.Evaluator_TransformToNTT(
+ NativePtr, encrypted.NativePtr, destinationNTT.NativePtr);
+ }
+
+ ///
+ /// Transforms a ciphertext back from NTT domain.
+ ///
+ ///
+ /// Transforms a ciphertext back from NTT domain. This functions applies the inverse of
+ /// David Harvey's Number Theoretic Transform separately to each polynomial of a ciphertext.
+ ///
+ /// The ciphertext to transform
+ /// if encryptedNTT is null
+ /// if encryptedNTT is not valid for the encryption parameters
+ /// if encryptedNTT is not in NTT form
+ /// if result ciphertext is transparent
+ public void TransformFromNTTInplace(Ciphertext encryptedNTT)
+ {
+ TransformFromNTT(encryptedNTT, destination: encryptedNTT);
+ }
+
+ ///
+ /// Transforms a ciphertext back from NTT domain.
+ ///
+ ///
+ /// Transforms a ciphertext back from NTT domain. This functions applies the inverse of
+ /// David Harvey's Number Theoretic Transform separately to each polynomial of a ciphertext.
+ /// The result is stored in the destination parameter.
+ ///
+ /// The ciphertext to transform
+ /// The ciphertext to overwrite with the transformed result
+ /// if either encryptedNTT or destination are null
+ /// if encryptedNTT is not valid for the encryption parameters
+ /// if encryptedNTT is not in NTT form
+ /// if result ciphertext is transparent
+ public void TransformFromNTT(Ciphertext encryptedNTT, Ciphertext destination)
+ {
+ if (null == encryptedNTT)
+ throw new ArgumentNullException(nameof(encryptedNTT));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.Evaluator_TransformFromNTT(
+ NativePtr, encryptedNTT.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Applies a Galois automorphism to a ciphertext.
+ ///
+ ///
+ ///
+ /// Applies a Galois automorphism to a ciphertext. To evaluate the Galois automorphism,
+ /// an appropriate set of Galois keys must also be provided. Dynamic memory allocations
+ /// in the process are allocated from the memory pool pointed to by the given
+ /// MemoryPoolHandle.
+ ///
+ ///
+ /// The desired Galois automorphism is given as a Galois element, and must be an odd
+ /// integer in the interval [1, M-1], where M = 2*N, and N = PolyModulusDegree. Used
+ /// with batching, a Galois element 3^i % M corresponds to a cyclic row rotation i steps
+ /// to the left, and a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation
+ /// i steps to the right. The Galois element M-1 corresponds to a column rotation (row
+ /// swap) in BFV, and complex conjugation in CKKS. In the polynomial view (not batching),
+ /// a Galois automorphism by a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)).
+ ///
+ ///
+ /// The ciphertext to apply the Galois automorphism to
+ /// The Galois element
+ /// The Galois keys
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or galoisKeys are null
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is not in the default NTT form
+ /// if encrypted has size larger than 2
+ /// if the Galois element is not valid
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void ApplyGaloisInplace(Ciphertext encrypted, uint galoisElt,
+ GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
+ {
+ ApplyGalois(encrypted, galoisElt, galoisKeys, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Applies a Galois automorphism to a ciphertext and writes the result to the
+ /// destination parameter.
+ ///
+ ///
+ ///
+ /// Applies a Galois automorphism to a ciphertext and writes the result to the
+ /// destination parameter. To evaluate the Galois automorphism, an appropriate set of
+ /// Galois keys must also be provided. Dynamic memory allocations in the process are
+ /// allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ ///
+ /// The desired Galois automorphism is given as a Galois element, and must be an odd
+ /// integer in the interval [1, M-1], where M = 2*N, and N = PolyModulusDegree. Used
+ /// with batching, a Galois element 3^i % M corresponds to a cyclic row rotation i steps
+ /// to the left, and a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation
+ /// i steps to the right. The Galois element M-1 corresponds to a column rotation (row
+ /// swap) in BFV, and complex conjugation in CKKS. In the polynomial view (not batching),
+ /// a Galois automorphism by a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)).
+ ///
+ ///
+ /// The ciphertext to apply the Galois automorphism to
+ /// The Galois element
+ /// The Galois keys
+ /// The ciphertext to overwrite with the result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, galoisKeys or destination are null
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is not in the default NTT form
+ /// if encrypted has size larger than 2
+ /// if the Galois element is not valid
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void ApplyGalois(Ciphertext encrypted, uint galoisElt, GaloisKeys galoisKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == galoisKeys)
+ throw new ArgumentNullException(nameof(galoisKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_ApplyGalois(
+ NativePtr, encrypted.NativePtr, galoisElt,
+ galoisKeys.NativePtr, destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Rotates plaintext matrix rows cyclically.
+ ///
+ ///
+ /// When batching is used with the BFV scheme, this function rotates the encrypted plaintext
+ /// matrix rows cyclically to the left (steps > 0) or to the right (steps < 0). Since
+ /// the size of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial
+ /// modulus, the number of steps to rotate must have absolute value at most N/2-1. Dynamic
+ /// memory allocations in the process are allocated from the memory pool pointed to by the
+ /// given MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The number of steps to rotate (negative left, positive right)
+ /// The Galois keys
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or galoisKeys are null
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.BFV
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is not in the default NTT form
+ /// if encrypted has size larger than 2
+ /// if steps has too big absolute value
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void RotateRowsInplace(Ciphertext encrypted,
+ int steps, GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
+ {
+ RotateRows(encrypted, steps, galoisKeys, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Rotates plaintext matrix rows cyclically.
+ ///
+ ///
+ /// When batching is used with the BFV scheme, this function rotates the encrypted plaintext
+ /// matrix rows cyclically to the left (steps > 0) or to the right (steps < 0) and writes
+ /// the result to the destination parameter. Since the size of the batched matrix is 2-by-(N/2),
+ /// where N is the degree of the polynomial modulus, the number of steps to rotate must have
+ /// absolute value at most N/2-1. Dynamic memory allocations in the process are allocated from
+ /// the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The number of steps to rotate (negative left, positive right)
+ /// The Galois keys
+ /// The ciphertext to overwrite with the rotated result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, galoisKeys or destination are null
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.BFV
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is in NTT form
+ /// if encrypted has size larger than 2
+ /// if steps has too big absolute value
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void RotateRows(Ciphertext encrypted, int steps, GaloisKeys galoisKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == galoisKeys)
+ throw new ArgumentNullException(nameof(galoisKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_RotateRows(
+ NativePtr, encrypted.NativePtr, steps, galoisKeys.NativePtr,
+ destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Rotates plaintext matrix columns cyclically.
+ ///
+ ///
+ /// When batching is used with the BFV scheme, this function rotates the encrypted
+ /// plaintext matrix columns cyclically. Since the size of the batched matrix is 2-by-(N/2),
+ /// where N is the degree of the polynomial modulus, this means simply swapping the two
+ /// rows. Dynamic memory allocations in the process are allocated from the memory pool
+ /// pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The Galois keys
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or galoisKeys are null
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.BFV
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is in NTT form
+ /// if encrypted has size larger than 2
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void RotateColumnsInplace(Ciphertext encrypted, GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
+ {
+ RotateColumns(encrypted, galoisKeys, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Rotates plaintext matrix columns cyclically.
+ ///
+ ///
+ /// When batching is used with the BFV scheme, this function rotates the encrypted plaintext
+ /// matrix columns cyclically, and writes the result to the destination parameter. Since the
+ /// size of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial modulus,
+ /// this means simply swapping the two rows. Dynamic memory allocations in the process are
+ /// allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The Galois keys
+ /// The ciphertext to overwrite with the rotated result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, galoisKeys or destination are null
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.BFV
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is in NTT form
+ /// if encrypted has size larger than 2
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void RotateColumns(Ciphertext encrypted, GaloisKeys galoisKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == galoisKeys)
+ throw new ArgumentNullException(nameof(galoisKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_RotateColumns(
+ NativePtr, encrypted.NativePtr, galoisKeys.NativePtr,
+ destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Rotates plaintext vector cyclically.
+ ///
+ ///
+ /// When using the CKKS scheme, this function rotates the encrypted plaintext vector
+ /// cyclically to the left (steps > 0) or to the right (steps < 0). Since the size
+ /// of the batched matrix is 2-by-(N/2), where N is the degree of the polynomial modulus,
+ /// the number of steps to rotate must have absolute value at most N/2-1. Dynamic memory
+ /// allocations in the process are allocated from the memory pool pointed to by the given
+ /// MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The number of steps to rotate (negative left, positive right)
+ /// The Galois keys
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or galoisKeys are null
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.CKKS
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is in NTT form
+ /// if encrypted has size larger than 2
+ /// if steps has too big absolute value
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void RotateVectorInplace(Ciphertext encrypted, int steps,
+ GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
+ {
+ RotateVector(encrypted, steps, galoisKeys, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Rotates plaintext vector cyclically.
+ ///
+ ///
+ /// When using the CKKS scheme, this function rotates the encrypted plaintext vector
+ /// cyclically to the left (steps > 0) or to the right (steps < 0) and writes
+ /// the result to the destination parameter. Since the size of the batched matrix is
+ /// 2-by-(N/2), where N is the degree of the polynomial modulus, the number of steps
+ /// to rotate must have absolute value at most N/2-1. Dynamic memory allocations in the
+ /// process are allocated from the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The number of steps to rotate (negative left, positive right)
+ /// The Galois keys
+ /// The ciphertext to overwrite with the rotated result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted, galoisKeys or destination are null
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.CKKS
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is in NTT form
+ /// if encrypted has size larger than 2
+ /// if steps has too big absolute value
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void RotateVector(Ciphertext encrypted, int steps, GaloisKeys galoisKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == galoisKeys)
+ throw new ArgumentNullException(nameof(galoisKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_RotateVector(
+ NativePtr, encrypted.NativePtr, steps, galoisKeys.NativePtr,
+ destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Complex conjugates plaintext slot values.
+ ///
+ ///
+ /// When using the CKKS scheme, this function complex conjugates all values in the
+ /// underlying plaintext. Dynamic memory allocations in the process are allocated from
+ /// the memory pool pointed to by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The Galois keys
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either encrypted or galoisKeys are null
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.CKKS
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is in NTT form
+ /// if encrypted has size larger than 2
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void ComplexConjugateInplace(Ciphertext encrypted, GaloisKeys galoisKeys, MemoryPoolHandle pool = null)
+ {
+ ComplexConjugate(encrypted, galoisKeys, destination: encrypted, pool: pool);
+ }
+
+ ///
+ /// Complex conjugates plaintext slot values.
+ ///
+ ///
+ /// When using the CKKS scheme, this function complex conjugates all values in the
+ /// underlying plaintext, and writes the result to the destination parameter. Dynamic
+ /// memory allocations in the process are allocated from the memory pool pointed to
+ /// by the given MemoryPoolHandle.
+ ///
+ /// The ciphertext to rotate
+ /// The Galois keys
+ /// The ciphertext to overwrite with the rotated result
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if the encryption parameters do not support batching
+ /// if scheme is not SchemeType.CKKS
+ /// if encrypted or galoisKeys is not valid for the
+ /// encryption parameters
+ /// if galoisKeys do not correspond to the top level
+ /// parameters in the current context
+ /// if encrypted is in NTT form
+ /// if encrypted has size larger than 2
+ /// if necessary Galois keys are not present
+ /// if pool is uninitialized
+ /// if keyswitching is not supported by the context
+ /// if result ciphertext is transparent
+ public void ComplexConjugate(Ciphertext encrypted, GaloisKeys galoisKeys,
+ Ciphertext destination, MemoryPoolHandle pool = null)
+ {
+ if (null == encrypted)
+ throw new ArgumentNullException(nameof(encrypted));
+ if (null == galoisKeys)
+ throw new ArgumentNullException(nameof(galoisKeys));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+ if (!ContextUsingKeyswitching)
+ throw new InvalidOperationException("Keyswitching is not supported by the context");
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+ NativeMethods.Evaluator_ComplexConjugate(
+ NativePtr, encrypted.NativePtr, galoisKeys.NativePtr,
+ destination.NativePtr, poolPtr);
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.Evaluator_Destroy(NativePtr);
+ }
+
+ internal bool ContextUsingKeyswitching
+ {
+ get
+ {
+ NativeMethods.Evaluator_ContextUsingKeyswitching(NativePtr, out bool result);
+ return result;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/bigpiseal3.5.1/dotnet/src/GaloisKeys.cs b/bigpiseal3.5.1/dotnet/src/GaloisKeys.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2fdfa73290a3fb140d6519cc7ede2b4a5636e2f0
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/GaloisKeys.cs
@@ -0,0 +1,116 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Class to store Galois keys.
+ ///
+ ///
+ ///
+ /// Slot rotations
+ /// Galois keys are certain types of public keys that are needed to perform encrypted
+ /// vector rotation operations on batched ciphertexts. Batched ciphertexts encrypt
+ /// a 2-by-(N/2) matrix of modular integers in the BFV scheme, or an N/2-dimensional
+ /// vector of complex numbers in the CKKS scheme, where N denotes the degree of the
+ /// polynomial modulus. In the BFV scheme Galois keys can enable both cyclic rotations
+ /// of the encrypted matrix rows, as well as row swaps (column rotations). In the CKKS
+ /// scheme Galois keys can enable cyclic vector rotations, as well as a complex
+ /// conjugation operation.
+ ///
+ ///
+ /// Thread Safety
+ /// In general, reading from GaloisKeys is thread-safe as long as no other thread is
+ /// concurrently mutating it. This is due to the underlying data structure storing
+ /// the Galois keys not being thread-safe.
+ ///
+ ///
+ public class GaloisKeys :
+ KSwitchKeys,
+ ISettable
+ {
+ ///
+ /// Creates an empty set of Galois keys.
+ ///
+ public GaloisKeys() : base()
+ {
+ }
+
+ ///
+ /// Creates a new GaloisKeys instance by copying a given instance.
+ ///
+ /// The GaloisKeys to copy from
+ /// if copy is null
+ public GaloisKeys(GaloisKeys copy)
+ : base(copy)
+ {
+ }
+
+ ///
+ /// Creates a new GaloisKeys instance initialized with a pointer to a native
+ /// KSwitchKeys object.
+ ///
+ /// Pointer to native KSwitchKeys object
+ /// Whether this instance owns the native pointer
+ internal GaloisKeys(IntPtr kswitchKeys, bool owned = true)
+ : base(kswitchKeys, owned)
+ {
+ }
+
+ ///
+ /// Copies a given GaloisKeys instance to the current one.
+ ///
+ ///
+ /// The GaloisKeys to copy from
+ /// if assign is null
+ public void Set(GaloisKeys assign)
+ {
+ base.Set(assign);
+ }
+
+ ///
+ /// Returns the index of a Galois key in the backing KSwitchKeys instance that
+ /// corresponds to the given Galois element, assuming that it exists in the
+ /// backing KSwitchKeys.
+ ///
+ /// The Galois element
+ /// if Galois element is not valid
+ public static ulong GetIndex(uint galoisElt)
+ {
+ NativeMethods.GaloisKeys_GetIndex(galoisElt, out ulong index);
+ return index;
+ }
+
+ ///
+ /// Returns whether a Galois key corresponding to a given Galois key element
+ /// exists.
+ ///
+ /// The Galois element
+ /// if Galois element is not valid
+ public bool HasKey(uint galoisElt)
+ {
+ ulong index = GetIndex(galoisElt);
+ return (ulong)Data.LongCount() > index &&
+ Data.ElementAt(checked((int)index)).Count() != 0;
+ }
+
+ ///
+ /// Returns a specified Galois key.
+ ///
+ ///
+ /// Returns a specified Galois key. The returned Galois key corresponds to the
+ /// given Galois element and is valid only as long as the GaloisKeys is valid.
+ ///
+ /// The Galois element
+ /// if the key corresponding to galoisElt
+ /// does not exist
+ public IEnumerable Key(uint galoisElt)
+ {
+ return Data.ElementAt(checked((int)GetIndex(galoisElt)));
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/IntegerEncoder.cs b/bigpiseal3.5.1/dotnet/src/IntegerEncoder.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dcfd98dc11ed8a4eb9d1554722a8a595764c540f
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/IntegerEncoder.cs
@@ -0,0 +1,329 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Encodes integers into plaintext polynomials that Encryptor can encrypt. An instance of
+ /// the IntegerEncoder class converts an integer into a plaintext polynomial by placing its
+ /// binary digits as the coefficients of the polynomial. Decoding the integer amounts to
+ /// evaluating the plaintext polynomial at x=2.
+ ///
+ /// Addition and multiplication on the integer side translate into addition and multiplication
+ /// on the encoded plaintext polynomial side, provided that the length of the polynomial
+ /// never grows to be of the size of the polynomial modulus (PolyModulus), and that the
+ /// coefficients of the plaintext polynomials appearing throughout the computations never
+ /// experience coefficients larger than the plaintext modulus (PlainModulus).
+ ///
+ ///
+ ///
+ /// Negative Integers
+ /// Negative integers are represented by using -1 instead of 1 in the binary representation,
+ /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
+ /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
+ /// would be stored as a polynomial coefficient PlainModulus-1.
+ ///
+ ///
+ public class IntegerEncoder : NativeObject
+ {
+ ///
+ /// Creates a IntegerEncoder object. The constructor takes as input a pointer to
+ /// a SEALContext object which contains the plaintext modulus.
+ ///
+ /// The SEALContext
+ /// if context is null
+ /// if the context is not set
+ /// if the PlainModulus set in context is not
+ /// at least 2
+ public IntegerEncoder(SEALContext context)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+
+ SEALContext.ContextData contextData = context.FirstContextData;
+ if (contextData.Parms.Scheme != SchemeType.BFV)
+ throw new ArgumentException("Unsupported scheme");
+
+ NativeMethods.IntegerEncoder_Create(context.NativePtr, out IntPtr encoderPtr);
+ NativePtr = encoderPtr;
+ }
+
+ ///
+ /// Encodes an unsigned integer (represented by ulong) into a plaintext polynomial.
+ ///
+ /// The unsigned integer to encode
+ public Plaintext Encode(ulong value)
+ {
+ Plaintext plain = new Plaintext();
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
+ return plain;
+ }
+
+ ///
+ /// Encodes an unsigned integer(represented by ulong) into a plaintext polynomial.
+ ///
+ /// The unsigned integer to encode
+ /// The plaintext to overwrite with the encoding
+ /// if destination is null
+ public void Encode(ulong value, Plaintext destination)
+ {
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
+ }
+
+ ///
+ /// Decodes a plaintext polynomial and returns the result as uint. Mathematically
+ /// this amounts to evaluating the input polynomial at X = 2.
+ ///
+ /// The plaintext to be decoded
+ /// if plain is null
+ /// if plain does not represent a valid plaintext polynomial
+ /// if the output does not fit in uint
+ public uint DecodeUInt32(Plaintext plain)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ NativeMethods.IntegerEncoder_DecodeUInt32(NativePtr, plain.NativePtr, out uint result);
+ return result;
+ }
+
+ ///
+ /// Decodes a plaintext polynomial and returns the result as ulong. Mathematically
+ /// this amounts to evaluating the input polynomial at X=2.
+ ///
+ /// The plaintext to be decoded
+ /// if plain is null
+ /// if plain does not represent a valid plaintext polynomial
+ /// if the output does not fit in ulong
+ public ulong DecodeUInt64(Plaintext plain)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ NativeMethods.IntegerEncoder_DecodeUInt64(NativePtr, plain.NativePtr, out ulong result);
+ return result;
+ }
+
+ ///
+ /// Encodes a signed integer (represented by long) into a plaintext polynomial.
+ ///
+ ///
+ ///
+ /// Negative Integers
+ /// Negative integers are represented by using -1 instead of 1 in the binary representation,
+ /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
+ /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
+ /// would be stored as a polynomial coefficient PlainModulus-1.
+ ///
+ ///
+ /// The signed integer to encode
+ public Plaintext Encode(long value)
+ {
+ Plaintext plain = new Plaintext();
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
+ return plain;
+ }
+
+ ///
+ /// Encodes a signed integer(represented by long) into a plaintext polynomial.
+ ///
+ ///
+ ///
+ /// Negative Integers
+ /// Negative integers are represented by using -1 instead of 1 in the binary representation,
+ /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
+ /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
+ /// would be stored as a polynomial coefficient PlainModulus-1.
+ ///
+ ///
+ /// The signed integer to encode
+ /// The plaintext to overwrite with the encoding
+ public void Encode(long value, Plaintext destination)
+ {
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
+ }
+
+ ///
+ /// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial.
+ ///
+ /// The unsigned integer to encode
+ /// if value is null
+ public Plaintext Encode(BigUInt value)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+
+ Plaintext plain = new Plaintext();
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, plain.NativePtr);
+ return plain;
+ }
+
+ ///
+ /// Encodes an unsigned integer(represented by BigUInt) into a plaintext polynomial.
+ ///
+ /// The unsigned integer to encode
+ /// The plaintext to overwrite with the encoding
+ /// if either value or destination are null
+ public void Encode(BigUInt value, Plaintext destination)
+ {
+ if (null == value)
+ throw new ArgumentNullException(nameof(value));
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value.NativePtr, destination.NativePtr);
+ }
+
+ ///
+ /// Decodes a plaintext polynomial and returns the result as int. Mathematically
+ /// this amounts to evaluating the input polynomial at X = 2.
+ ///
+ /// The plaintext to be decoded
+ /// if plain is null
+ /// if plain does not represent a valid plaintext polynomial
+ /// if the output does not fit in int
+ public int DecodeInt32(Plaintext plain)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ NativeMethods.IntegerEncoder_DecodeInt32(NativePtr, plain.NativePtr, out int result);
+ return result;
+ }
+
+ ///
+ /// Decodes a plaintext polynomial and returns the result as long. Mathematically
+ /// this amounts to evaluating the input polynomial at X = 2.
+ ///
+ /// The plaintext to be decoded
+ /// if plain is null
+ /// if plain does not represent a valid plaintext polynomial
+ /// if the output does not fit in long
+ public long DecodeInt64(Plaintext plain)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ NativeMethods.IntegerEncoder_DecodeInt64(NativePtr, plain.NativePtr, out long result);
+ return result;
+ }
+
+ ///
+ /// Decodes a plaintext polynomial and returns the result as BigUInt.
+ /// Mathematically this amounts to evaluating the input polynomial at X = 2.
+ ///
+ /// The plaintext to be decoded
+ /// if plain is null
+ /// if plain does not represent a valid plaintext polynomial
+ /// if the output is negative
+ public BigUInt DecodeBigUInt(Plaintext plain)
+ {
+ if (null == plain)
+ throw new ArgumentNullException(nameof(plain));
+
+ NativeMethods.IntegerEncoder_DecodeBigUInt(NativePtr, plain.NativePtr, out IntPtr buiPtr);
+ BigUInt bui = new BigUInt(buiPtr);
+ return bui;
+ }
+
+ ///
+ /// Encodes a signed integer(represented by int) into a plaintext polynomial.
+ ///
+ ///
+ ///
+ /// Negative Integers
+ /// Negative integers are represented by using -1 instead of 1 in the binary representation,
+ /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
+ /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
+ /// would be stored as a polynomial coefficient PlainModulus-1.
+ ///
+ ///
+ /// The signed integer to encode
+ public Plaintext Encode(int value)
+ {
+ Plaintext plain = new Plaintext();
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
+ return plain;
+ }
+
+ ///
+ /// Encodes an unsigned integer(represented by uint) into a plaintext polynomial.
+ ///
+ /// The unsigned integer to encode
+ public Plaintext Encode(uint value)
+ {
+ Plaintext plain = new Plaintext();
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, plain.NativePtr);
+ return plain;
+ }
+
+ ///
+ /// Encodes a signed integer(represented by int) into a plaintext polynomial.
+ ///
+ ///
+ ///
+ /// Negative Integers
+ /// Negative integers are represented by using -1 instead of 1 in the binary representation,
+ /// and the negative coefficients are stored in the plaintext polynomials as unsigned integers
+ /// that represent them modulo the plaintext modulus. Thus, for example, a coefficient of -1
+ /// would be stored as a polynomial coefficient PlainModulus-1.
+ ///
+ ///
+ /// The signed integer to encode
+ /// The plaintext to overwrite with the encoding
+ /// if destination is null
+ public void Encode(int value, Plaintext destination)
+ {
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
+ }
+
+ ///
+ /// Encodes an unsigned integer(represented by uint) into a plaintext polynomial.
+ ///
+ /// The unsigned integer to encode
+ /// The plaintext to overwrite with the encoding
+ /// if destination is null
+ public void Encode(uint value, Plaintext destination)
+ {
+ if (null == destination)
+ throw new ArgumentNullException(nameof(destination));
+
+ NativeMethods.IntegerEncoder_Encode(NativePtr, value, destination.NativePtr);
+ }
+
+ ///
+ /// Get a copy of the plaintext modulus.
+ ///
+ public Modulus PlainModulus
+ {
+ get
+ {
+ NativeMethods.IntegerEncoder_PlainModulus(NativePtr, out IntPtr sm);
+ Modulus result = new Modulus(sm);
+ return result;
+ }
+ }
+
+ ///
+ /// Destroy the native object
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.IntegerEncoder_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/KSwitchKeys.cs b/bigpiseal3.5.1/dotnet/src/KSwitchKeys.cs
new file mode 100644
index 0000000000000000000000000000000000000000..872700cbc7e6dcdf4686e85e913a227603cc0756
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/KSwitchKeys.cs
@@ -0,0 +1,289 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Class to store keyswitching keys.
+ ///
+ ///
+ ///
+ ///
+ /// Class to store keyswitching keys. It should never be necessary for normal
+ /// users to create an instance of KSwitchKeys. This class is used strictly as
+ /// a base class for RelinKeys and GaloisKeys classes.
+ ///
+ ///
+ /// Concretely, keyswitching is used to change a ciphertext encrypted with one
+ /// key to be encrypted with another key.It is a general technique and is used
+ /// in relinearization and Galois rotations. A keyswitching key contains a sequence
+ /// (vector) of keys.In RelinKeys, each key is an encryption of a power of the
+ /// secret key.In GaloisKeys, each key corresponds to a type of rotation.
+ ///
+ ///
+ /// In general, reading from KSwitchKeys is thread-safe as long as no
+ /// other thread is concurrently mutating it.This is due to the underlying
+ /// data structure storing the keyswitching keys not being thread-safe.
+ ///
+ ///
+ public class KSwitchKeys :
+ NativeObject,
+ ISerializableObject,
+ ISettable
+ {
+ ///
+ /// Creates an empty KSwitchKeys.
+ ///
+ public KSwitchKeys()
+ {
+ NativeMethods.KSwitchKeys_Create(out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a new KSwitchKeys instance by copying a given instance.
+ ///
+ /// The KSwitchKeys to copy from
+ /// if copy is null
+ public KSwitchKeys(KSwitchKeys copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.KSwitchKeys_Create(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a new KSwitchKeys instance initialized with a pointer to a native
+ /// KSwitchKeys object.
+ ///
+ /// Pointer to native KSwitchKeys object
+ /// Whether this instance owns the native pointer
+ internal KSwitchKeys(IntPtr kswitchKeys, bool owned = true)
+ : base(kswitchKeys, owned)
+ {
+ }
+
+ ///
+ /// Copies a given KSwitchKeys instance to the current one.
+ ///
+ ///
+ /// The KSwitchKeys to copy from
+ /// if assign is null
+ public void Set(KSwitchKeys assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.KSwitchKeys_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Returns the current number of keyswitching keys. Only keys that are non-empty
+ /// are counted.
+ ///
+ public ulong Size
+ {
+ get
+ {
+ NativeMethods.KSwitchKeys_Size(NativePtr, out ulong size);
+ return size;
+ }
+ }
+
+ ///
+ /// Returns the KSwitchKeys data.
+ ///
+ ///
+ /// Returns the KSwitchKeys data. The returned object is valid only as long as
+ /// the KSwitchKeys is valid and not changed.
+ ///
+ public IEnumerable> Data
+ {
+ get
+ {
+ List> result = new List>();
+ NativeMethods.KSwitchKeys_RawSize(NativePtr, out ulong size);
+
+ for (ulong i = 0; i < size; i++)
+ {
+ ulong count = 0;
+ NativeMethods.KSwitchKeys_GetKeyList(NativePtr, i, ref count, null);
+
+ IntPtr[] pointers = new IntPtr[count];
+ NativeMethods.KSwitchKeys_GetKeyList(NativePtr, i, ref count, pointers);
+
+ List key = new List(checked((int)count));
+ foreach (IntPtr ptr in pointers)
+ {
+ key.Add(new PublicKey(ptr, owned: false));
+ }
+
+ result.Add(key);
+ }
+
+ return result;
+ }
+ }
+
+ ///
+ /// Returns a copy of ParmsId.
+ ///
+ public ParmsId ParmsId
+ {
+ get
+ {
+ ParmsId parms = new ParmsId();
+ NativeMethods.KSwitchKeys_GetParmsId(NativePtr, parms.Block);
+ return parms;
+ }
+ private set
+ {
+ NativeMethods.KSwitchKeys_SetParmsId(NativePtr, value.Block);
+ }
+ }
+
+ ///
+ /// Returns an upper bound on the size of the KSwitchKeys, as if it was written
+ /// to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.KSwitchKeys_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the KSwitchKeys to an output stream.
+ ///
+ /// Saves the KSwitchKeys to an output stream. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the KSwitchKeys to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.KSwitchKeys_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ /// Loads a KSwitchKeys from an input stream overwriting the current
+ /// KSwitchKeys.
+ ///
+ /// Loads a KSwitchKeys from an input stream overwriting the current
+ /// KSwitchKeys. No checking of the validity of the KSwitchKeys data against
+ /// encryption parameters is performed. This function should not be used
+ /// unless the KSwitchKeys comes from a fully trusted source.
+ ///
+ /// The SEALContext
+ /// The stream to load the KSwitchKeys from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long UnsafeLoad(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.KSwitchKeys_UnsafeLoad(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ /// Loads a KSwitchKeys from an input stream overwriting the current
+ /// KSwitchKeys.
+ ///
+ /// Loads a KSwitchKeys from an input stream overwriting the current
+ /// KSwitchKeys. The loaded KSwitchKeys is verified to be valid for the given
+ /// SEALContext.
+ ///
+ /// The SEALContext
+ /// The stream to load the KSwitchKeys from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long Load(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.KSwitchKeys_Load(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ ///
+ /// Returns the currently used MemoryPoolHandle.
+ ///
+ public MemoryPoolHandle Pool
+ {
+ get
+ {
+ NativeMethods.KSwitchKeys_Pool(NativePtr, out IntPtr pool);
+ MemoryPoolHandle handle = new MemoryPoolHandle(pool);
+ return handle;
+ }
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.KSwitchKeys_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/KeyGenerator.cs b/bigpiseal3.5.1/dotnet/src/KeyGenerator.cs
new file mode 100644
index 0000000000000000000000000000000000000000..604b56ef6e43c886f9963c3a04e2a9159bb96427
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/KeyGenerator.cs
@@ -0,0 +1,380 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Generates matching secret key and public key.
+ ///
+ ///
+ /// Generates matching secret key and public key. An existing KeyGenerator can
+ /// also at any time be used to generate relinearization keys and Galois keys.
+ /// Constructing a KeyGenerator requires only a SEALContext.
+ ///
+ public class KeyGenerator : NativeObject
+ {
+ ///
+ /// Creates a KeyGenerator initialized with the specified SEALContext.
+ ///
+ ///
+ /// Creates a KeyGenerator initialized with the specified .
+ /// Dynamically allocated member variables are allocated from the global memory pool.
+ ///
+ /// The SEALContext
+ /// if encryption parameters are not
+ /// valid
+ /// if context is null
+ public KeyGenerator(SEALContext context)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+
+ NativeMethods.KeyGenerator_Create(context.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates an KeyGenerator instance initialized with the specified
+ /// SEALContext and specified previously secret key.
+ ///
+ ///
+ /// Creates an KeyGenerator instance initialized with the specified
+ /// SEALContext and specified previously secret key. This can e.g. be used
+ /// to increase the number of relinearization keys from what had earlier
+ /// been generated, or to generate Galois keys in case they had not been
+ /// generated earlier.
+ ///
+ /// The SEALContext
+ /// A previously generated secret key
+ /// if either context or secretKey
+ /// are null
+ /// if encryption parameters are not
+ /// valid
+ /// if secretKey or publicKey is not
+ /// valid for encryption parameters
+ public KeyGenerator(SEALContext context, SecretKey secretKey)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+ if (null == secretKey)
+ throw new ArgumentNullException(nameof(secretKey));
+ if (!context.ParametersSet)
+ throw new ArgumentException("Encryption parameters are not set correctly");
+ if (!ValCheck.IsValidFor(secretKey, context))
+ throw new ArgumentException("Secret key is not valid for encryption parameters");
+
+ NativeMethods.KeyGenerator_Create(context.NativePtr,
+ secretKey.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Generates and returns a public key. Every time this function is called,
+ /// a new public key will be generated.
+ ///
+ public PublicKey PublicKey
+ {
+ get
+ {
+ NativeMethods.KeyGenerator_PublicKey(NativePtr, out IntPtr pubKeyPtr);
+ PublicKey pubKey = new PublicKey(pubKeyPtr);
+ return pubKey;
+ }
+ }
+
+ ///
+ /// Returns a copy of the secret key.
+ ///
+ public SecretKey SecretKey
+ {
+ get
+ {
+ NativeMethods.KeyGenerator_SecretKey(NativePtr, out IntPtr secretKeyPtr);
+ SecretKey secretKey = new SecretKey(secretKeyPtr);
+ return secretKey;
+ }
+ }
+
+ ///
+ /// Generates and returns relinearization keys.
+ ///
+ ///
+ /// Generates and returns relinearization keys. This function returns
+ /// relinearization keys in a fully expanded form and is meant to be used
+ /// primarily for demo, testing, and debugging purposes.
+ ///
+ /// if the encryption
+ /// parameters do not support keyswitching
+ public RelinKeys RelinKeysLocal()
+ {
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ NativeMethods.KeyGenerator_RelinKeys(NativePtr, false, out IntPtr relinKeysPtr);
+ return new RelinKeys(relinKeysPtr);
+ }
+
+ ///
+ /// Generates and returns relinearization keys as a serializable object.
+ ///
+ ///
+ ///
+ /// Generates and returns relinearization keys as a serializable object.
+ ///
+ ///
+ /// Half of the key data is pseudo-randomly generated from a seed to reduce
+ /// the object size. The resulting serializable object cannot be used
+ /// directly and is meant to be serialized for the size reduction to have an
+ /// impact.
+ ///
+ ///
+ /// if the encryption
+ /// parameters do not support keyswitching
+ public Serializable RelinKeys()
+ {
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ NativeMethods.KeyGenerator_RelinKeys(NativePtr, true, out IntPtr relinKeysPtr);
+ RelinKeys relinKeys = new RelinKeys(relinKeysPtr);
+ return new Serializable(relinKeys);
+ }
+
+ ///
+ /// Generates and returns Galois keys.
+ ///
+ ///
+ ///
+ /// Generates and returns Galois keys. This function returns Galois keys in
+ /// a fully expanded form and is meant to be used primarily for demo, testing,
+ /// and debugging purposes. This function creates specific Galois keys that
+ /// can be used to apply specific Galois automorphisms on encrypted data. The
+ /// user needs to give as input a vector of Galois elements corresponding to
+ /// the keys that are to be created.
+ ///
+ ///
+ /// The Galois elements are odd integers in the interval [1, M-1], where
+ /// M = 2*N, and N = PolyModulusDegree. Used with batching, a Galois element
+ /// 3^i % M corresponds to a cyclic row rotation i steps to the left, and
+ /// a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i
+ /// steps to the right. The Galois element M-1 corresponds to a column rotation
+ /// (row swap). In the polynomial view (not batching), a Galois automorphism by
+ /// a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)).
+ ///
+ ///
+ /// The Galois elements for which to generate keys
+ /// if the encryption parameters
+ /// do not support batching and scheme is SchemeType.BFV
+ /// if the encryption
+ /// parameters do not support keyswitching
+ /// if the Galois elements are not valid
+ public GaloisKeys GaloisKeysLocal(IEnumerable galoisElts)
+ {
+ if (null == galoisElts)
+ throw new ArgumentNullException(nameof(galoisElts));
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ uint[] galoisEltsArr = galoisElts.ToArray();
+ NativeMethods.KeyGenerator_GaloisKeysFromElts(NativePtr,
+ (ulong)galoisEltsArr.Length, galoisEltsArr, false, out IntPtr galoisKeysPtr);
+ return new GaloisKeys(galoisKeysPtr);
+ }
+
+ ///
+ /// Generates and returns Galois keys as a serializable object.
+ ///
+ ///
+ ///
+ /// Generates and returns Galois keys as a serializable object. This function
+ /// creates specific Galois keys that can be used to apply specific Galois
+ /// automorphisms on encrypted data. The user needs to give as input a vector
+ /// of Galois elements corresponding to the keys that are to be created.
+ ///
+ ///
+ /// The Galois elements are odd integers in the interval [1, M-1], where
+ /// M = 2*N, and N = PolyModulusDegree. Used with batching, a Galois element
+ /// 3^i % M corresponds to a cyclic row rotation i steps to the left, and
+ /// a Galois element 3^(N/2-i) % M corresponds to a cyclic row rotation i
+ /// steps to the right. The Galois element M-1 corresponds to a column rotation
+ /// (row swap). In the polynomial view (not batching), a Galois automorphism by
+ /// a Galois element p changes Enc(plain(x)) to Enc(plain(x^p)).
+ ///
+ ///
+ /// Half of the key data is pseudo-randomly generated from a seed to reduce
+ /// the object size. The resulting serializable object cannot be used
+ /// directly and is meant to be serialized for the size reduction to have an
+ /// impact.
+ ///
+ ///
+ /// The Galois elements for which to generate keys
+ /// if galoisElts is null
+ /// if the encryption parameters
+ /// do not support batching and scheme is SchemeType.BFV
+ /// if the encryption
+ /// parameters do not support keyswitching
+ /// if the Galois elements are not valid
+ public Serializable GaloisKeys(IEnumerable galoisElts)
+ {
+ if (null == galoisElts)
+ throw new ArgumentNullException(nameof(galoisElts));
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ uint[] galoisEltsArr = galoisElts.ToArray();
+ NativeMethods.KeyGenerator_GaloisKeysFromElts(NativePtr,
+ (ulong)galoisEltsArr.Length, galoisEltsArr, true, out IntPtr galoisKeysPtr);
+ GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr);
+ return new Serializable(galoisKeys);
+ }
+
+ ///
+ /// Generates and returns Galois keys.
+ ///
+ ///
+ /// Generates and returns Galois keys. This function returns Galois keys in
+ /// a fully expanded form and is meant to be used primarily for demo, testing,
+ /// and debugging purposes. The user needs to give as input a vector of desired
+ /// Galois rotation step counts, where negative step counts correspond to
+ /// rotations to the right and positive step counts correspond to rotations to
+ /// the left. A step count of zero can be used to indicate a column rotation
+ /// in the BFV scheme complex conjugation in the CKKS scheme.
+ ///
+ /// The rotation step counts for which to generate keys
+ /// if steps is null
+ /// if the encryption parameters
+ /// do not support batching and scheme is SchemeType.BFV
+ /// if the encryption
+ /// parameters do not support keyswitching
+ /// if the step counts are not valid
+ public GaloisKeys GaloisKeysLocal(IEnumerable steps)
+ {
+ if (null == steps)
+ throw new ArgumentNullException(nameof(steps));
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ int[] stepsArr = steps.ToArray();
+ NativeMethods.KeyGenerator_GaloisKeysFromSteps(NativePtr,
+ (ulong)stepsArr.Length, stepsArr, false, out IntPtr galoisKeysPtr);
+ return new GaloisKeys(galoisKeysPtr);
+ }
+
+ ///
+ /// Generates and returns Galois keys as a serializable object.
+ ///
+ ///
+ ///
+ /// Generates and returns Galois keys as a serializable object. This function
+ /// creates specific Galois keys that can be used to apply specific Galois
+ /// automorphisms on encrypted data. The user needs to give as input a vector
+ /// of desired Galois rotation step counts, where negative step counts
+ /// correspond to rotations to the right and positive step counts correspond
+ /// to rotations to the left. A step count of zero can be used to indicate
+ /// a column rotation in the BFV scheme complex conjugation in the CKKS scheme.
+ ///
+ ///
+ /// Half of the key data is pseudo-randomly generated from a seed to reduce
+ /// the object size. The resulting serializable object cannot be used
+ /// directly and is meant to be serialized for the size reduction to have an
+ /// impact.
+ ///
+ ///
+ /// The rotation step counts for which to generate keys
+ /// if steps is null
+ /// if the encryption parameters
+ /// do not support batching and scheme is SchemeType.BFV
+ /// if the encryption
+ /// parameters do not support keyswitching
+ /// if the step counts are not valid
+ public Serializable GaloisKeys(IEnumerable steps)
+ {
+ if (null == steps)
+ throw new ArgumentNullException(nameof(steps));
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ int[] stepsArr = steps.ToArray();
+ NativeMethods.KeyGenerator_GaloisKeysFromSteps(NativePtr,
+ (ulong)stepsArr.Length, stepsArr, true, out IntPtr galoisKeysPtr);
+ GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr);
+ return new Serializable(galoisKeys);
+ }
+
+ ///
+ /// Generates and returns Galois keys.
+ ///
+ ///
+ /// Generates and returns Galois keys. This function returns Galois keys in
+ /// a fully expanded form and is meant to be used primarily for demo, testing,
+ /// and debugging purposes. This function creates logarithmically many (in
+ /// degree of the polynomial modulus) Galois keys that is sufficient to apply
+ /// any Galois automorphism (e.g. rotations) on encrypted data. Most users
+ /// will want to use this overload of the function.
+ ///
+ /// if the encryption parameters
+ /// do not support batching and scheme is SchemeType.BFV
+ /// if the encryption
+ /// parameters do not support keyswitching
+ public GaloisKeys GaloisKeysLocal()
+ {
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ NativeMethods.KeyGenerator_GaloisKeysAll(NativePtr, false, out IntPtr galoisKeysPtr);
+ return new GaloisKeys(galoisKeysPtr);
+ }
+
+ ///
+ /// Generates and returns Galois keys as a serializable object.
+ ///
+ ///
+ ///
+ /// Generates and returns Galois keys as a serializable object. This function
+ /// creates logarithmically many (in degree of the polynomial modulus) Galois
+ /// keys that is sufficient to apply any Galois automorphism (e.g. rotations)
+ /// on encrypted data. Most users will want to use this overload of the function.
+ ///
+ ///
+ /// Half of the key data is pseudo-randomly generated from a seed to reduce
+ /// the object size. The resulting serializable object cannot be used
+ /// directly and is meant to be serialized for the size reduction to have an
+ /// impact.
+ ///
+ ///
+ /// if the encryption parameters
+ /// do not support batching and scheme is SchemeType.BFV
+ /// if the encryption
+ /// parameters do not support keyswitching
+ public Serializable GaloisKeys()
+ {
+ if (!UsingKeyswitching())
+ throw new InvalidOperationException("Encryption parameters do not support keyswitching");
+
+ NativeMethods.KeyGenerator_GaloisKeysAll(NativePtr, true, out IntPtr galoisKeysPtr);
+ GaloisKeys galoisKeys = new GaloisKeys(galoisKeysPtr);
+ return new Serializable(galoisKeys);
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.KeyGenerator_Destroy(NativePtr);
+ }
+
+ internal bool UsingKeyswitching()
+ {
+ NativeMethods.KeyGenerator_ContextUsingKeyswitching(NativePtr, out bool result);
+ return result;
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/MMProf.cs b/bigpiseal3.5.1/dotnet/src/MMProf.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9cae5ec69a540df0836bc4625a6db2d77ad9c2bd
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/MMProf.cs
@@ -0,0 +1,115 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// The MMProf is a pure virtual class that every profile for the MemoryManager
+ /// should inherit from. The only functionality this class implements is the
+ /// GetPool() function that returns a MemoryPoolHandle pointing
+ /// to a pool selected by internal logic. The returned MemoryPoolHandle must
+ /// point to a valid memory pool.
+ ///
+ public abstract class MMProf : NativeObject
+ {
+ ///
+ /// Returns a MemoryPoolHandle pointing to a pool selected by internal logic
+ /// in a derived class.
+ ///
+ public MemoryPoolHandle GetPool()
+ {
+ NativeMethods.MMProf_GetPool(NativePtr, out IntPtr pool);
+ MemoryPoolHandle handle = new MemoryPoolHandle(pool);
+ return handle;
+ }
+
+ ///
+ /// Destroy native backing object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.MMProf_Destroy(NativePtr);
+ }
+ }
+
+ ///
+ /// A memory manager profile that always returns a MemoryPoolHandle pointing to
+ /// the global memory pool. Microsoft SEAL uses this memory manager profile by default.
+ ///
+ public class MMProfGlobal : MMProf
+ {
+ ///
+ /// Create a new instance of MMProfGlobal
+ ///
+ public MMProfGlobal()
+ {
+ NativeMethods.MMProf_CreateGlobal(out IntPtr profile);
+ NativePtr = profile;
+ }
+ }
+
+ ///
+ /// A memory manager profile that always returns a MemoryPoolHandle pointing to
+ /// specific memory pool.
+ ///
+ public class MMProfFixed : MMProf
+ {
+ ///
+ /// Create a new instance of MMProfFixed
+ ///
+ /// Fixed memory pool handle to use
+ /// if pool is null
+ public MMProfFixed(MemoryPoolHandle pool)
+ {
+ if (null == pool)
+ throw new ArgumentNullException(nameof(pool));
+
+ // Create a copy of MemoryPoolHandle, as the profile will take ownership
+ // of the pointer and will attempt to delete it when destroyed.
+ NativeMethods.MemoryPoolHandle_Create(pool.NativePtr, out IntPtr poolCopy);
+ NativeMethods.MMProf_CreateFixed(poolCopy, out IntPtr profile);
+ NativePtr = profile;
+ }
+ }
+
+ ///
+ /// A memory manager profile that always returns a MemoryPoolHandle pointing to
+ /// the new thread-safe memory pool. This profile should not be used except in
+ /// special circumstances, as it does not result in any reuse of allocated memory.
+ ///
+ public class MMProfNew : MMProf
+ {
+ ///
+ /// Create a new instance of MMProfNew
+ ///
+ public MMProfNew()
+ {
+ NativeMethods.MMProf_CreateNew(out IntPtr profile);
+ NativePtr = profile;
+ }
+ }
+
+ ///
+ /// A memory manager profile that always returns a MemoryPoolHandle pointing to
+ /// the thread-local memory pool. This profile should be used with care, as any
+ /// memory allocated by it will be released once the thread exits. In other words,
+ /// the thread-local memory pool cannot be used to share memory across different
+ /// threads. On the other hand, this profile can be useful when a very high number
+ /// of threads doing simultaneous allocations would cause contention in the
+ /// global memory pool.
+ ///
+ public class MMProfThreadLocal : MMProf
+ {
+ ///
+ /// Create a new instance of MMProfThreadLocal
+ ///
+ public MMProfThreadLocal()
+ {
+ NativeMethods.MMProf_CreateThreadLocal(out IntPtr profile);
+ NativePtr = profile;
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/MemoryManager.cs b/bigpiseal3.5.1/dotnet/src/MemoryManager.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9b02ba6783eaedac78886714102529ee10596dbf
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/MemoryManager.cs
@@ -0,0 +1,111 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Memory Manager Profile Options used in MemoryManager.GetPool method
+ ///
+ public enum MMProfOpt : ulong
+ {
+ ///
+ /// Use default profile
+ ///
+ Default = 0,
+
+ ///
+ /// Force use of the Global profile
+ ///
+ ForceGlobal = 1,
+
+ ///
+ /// Force use of a New profile
+ ///
+ ForceNew = 2,
+
+ ///
+ /// Force use of the Thread Local profile
+ ///
+ ForceThreadLocal = 4
+ }
+
+ ///
+ /// The MemoryManager class can be used to create instances of MemoryPoolHandle
+ /// based on a given "profile". A profile is implemented by inheriting from the
+ /// MMProf class (pure virtual) and encapsulates internal logic for deciding which
+ /// memory pool to use.
+ ///
+ public static class MemoryManager
+ {
+ ///
+ /// Static initialization of MemoryManager
+ ///
+ static MemoryManager()
+ {
+ // The default profile is Global
+ profile_ = new MMProfGlobal();
+ }
+
+ ///
+ /// Sets the current profile to a given one and returns an instance pointing
+ /// to the previously set profile.
+ ///
+ /// New memory manager profile
+ /// if newProfile is null
+ public static MMProf SwitchProfile(MMProf newProfile)
+ {
+ if (null == newProfile)
+ throw new ArgumentNullException(nameof(newProfile));
+
+ NativeMethods.MemoryManager_SwitchProfile(newProfile.NativePtr);
+
+ MMProf oldProfile = profile_;
+ profile_ = newProfile;
+
+ return oldProfile;
+ }
+
+ ///
+ /// Returns a MemoryPoolHandle according to the currently set memory manager
+ /// profile and profOpt. The following values for profOpt have an effect
+ /// independent of the current profile:
+ ///
+ /// MMProfOpt.ForceNew: return MemoryPoolHandle.New()
+ /// MMProfOpt.ForceGlobal: return MemoryPoolHandle.Global()
+ /// MMProfOpt.ForceThreadLocal: return MemoryPoolHandle.ThreadLocal()
+ ///
+ /// Other values for profOpt are forwarded to the current profile and, depending
+ /// on the profile, may or may not have an effect. The value MMProfOpt.Default
+ /// will always invoke a default behavior for the current profile.
+ ///
+ /// A MMProfOpt parameter used to provide additional
+ /// instructions to the memory manager profile for internal logic.
+ /// Indicates whether the memory pool data
+ /// should be cleared when destroyed.This can be important when memory pools
+ /// are used to store private data. This parameter is only used with MMProfOpt.ForceNew,
+ /// and ignored in all other cases.
+ public static MemoryPoolHandle GetPool(MMProfOpt profOpt, bool clearOnDestruction = false)
+ {
+ NativeMethods.MemoryManager_GetPool((int)profOpt, clearOnDestruction, out IntPtr handlePtr);
+ MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
+ return handle;
+ }
+
+ ///
+ /// Returns a MemoryPoolHandle according to the currently set memory manager profile.
+ ///
+ public static MemoryPoolHandle GetPool()
+ {
+ NativeMethods.MemoryManager_GetPool(out IntPtr handlePtr);
+ MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
+ return handle;
+ }
+
+ ///
+ /// Currently set profile
+ ///
+ private static MMProf profile_ = null;
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/MemoryPoolHandle.cs b/bigpiseal3.5.1/dotnet/src/MemoryPoolHandle.cs
new file mode 100644
index 0000000000000000000000000000000000000000..64911c99d0ca0d03c26c0d5dcac17bde4b12a898
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/MemoryPoolHandle.cs
@@ -0,0 +1,236 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Manages a shared pointer to a memory pool. Microsoft SEAL uses memory pools for
+ /// improved performance due to the large number of memory allocations needed
+ /// by the homomorphic encryption operations, and the underlying polynomial
+ /// arithmetic. The library automatically creates a shared global memory pool
+ /// that is used for all dynamic allocations by default, and the user can
+ /// optionally create any number of custom memory pools to be used instead.
+ ///
+ ///
+ ///
+ /// Uses in Multi-Threaded Applications
+ /// Sometimes the user might want to use specific memory pools for dynamic
+ /// allocations in certain functions. For example, in heavily multi-threaded
+ /// applications allocating concurrently from a shared memory pool might lead
+ /// to significant performance issues due to thread contention. For these cases
+ /// Microsoft SEAL provides overloads of the functions that take a MemoryPoolHandle as an
+ /// additional argument, and uses the associated memory pool for all dynamic
+ /// allocations inside the function. Whenever this functions is called, the
+ /// user can then simply pass a thread-local MemoryPoolHandle to be used.
+ ///
+ ///
+ /// Thread-Unsafe Memory Pools
+ /// While memory pools are by default thread-safe, in some cases it suffices
+ /// to have a memory pool be thread-unsafe. To get a little extra performance,
+ /// the user can optionally create such thread-unsafe memory pools and use them
+ /// just as they would use thread-safe memory pools.
+ ///
+ ///
+ /// Initialized and Uninitialized Handles
+ /// A MemoryPoolHandle has to be set to point either to the global memory pool,
+ /// or to a new memory pool. If this is not done, the MemoryPoolHandle is
+ /// said to be uninitialized, and cannot be used. Initialization simple means
+ /// assigning MemoryPoolHandle::Global() or MemoryPoolHandle::New() to it.
+ ///
+ ///
+ /// Managing Lifetime
+ /// Internally, the MemoryPoolHandle wraps a C++ shared pointer pointing to
+ /// a memory pool class. Thus, as long as a MemoryPoolHandle pointing to
+ /// a particular memory pool exists, the pool stays alive. Classes such as
+ /// Evaluator and Ciphertext store their own local copies of a MemoryPoolHandle
+ /// to guarantee that the pool stays alive as long as the managing object
+ /// itself stays alive. The global memory pool is implemented as a global
+ /// C++ std::shared_ptr to a memory pool class, and is thus expected to stay
+ /// alive for the entire duration of the program execution. Note that it can
+ /// be problematic to create other global objects that use the memory pool
+ /// e.g. in their constructor, as one would have to ensure the initialization
+ /// order of these global variables to be correct (i.e. global memory pool
+ /// first).
+ ///
+ ///
+ public class MemoryPoolHandle : NativeObject
+ {
+ ///
+ /// Creates a new uninitialized MemoryPoolHandle.
+ ///
+ public MemoryPoolHandle()
+ {
+ NativeMethods.MemoryPoolHandle_Create(out IntPtr handlePtr);
+ NativePtr = handlePtr;
+ }
+
+ ///
+ /// Creates a copy of a given MemoryPoolHandle. As a result, the created
+ /// MemoryPoolHandle will point to the same underlying memory pool as the
+ /// copied instance.
+ ///
+ /// The MemoryPoolHandle to copy from.
+ /// if copy is null.
+ public MemoryPoolHandle(MemoryPoolHandle copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.MemoryPoolHandle_Create(copy.NativePtr, out IntPtr handlePtr);
+ NativePtr = handlePtr;
+ }
+
+ ///
+ /// Create a MemoryPoolHandle through a native object pointer.
+ ///
+ /// Pointer to native MemoryPoolHandle
+ /// Whether this instance owns the native pointer
+ internal MemoryPoolHandle(IntPtr ptr, bool owned = true)
+ : base(ptr, owned)
+ {
+ }
+
+ ///
+ /// Overwrites the MemoryPoolHandle instance with the specified instance. As
+ /// a result, the current MemoryPoolHandle will point to the same underlying
+ /// memory pool as the assigned instance.
+ ///
+ /// The MemoryPoolHandle instance to assign to the current
+ /// instance
+ /// if assign is null.
+ public void Set(MemoryPoolHandle assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.MemoryPoolHandle_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Returns a MemoryPoolHandle pointing to the global memory pool.
+ ///
+ public static MemoryPoolHandle Global()
+ {
+ NativeMethods.MemoryPoolHandle_Global(out IntPtr handlePtr);
+ MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
+ return handle;
+ }
+
+ ///
+ /// Returns a MemoryPoolHandle pointing to the thread-local memory pool.
+ ///
+ public static MemoryPoolHandle ThreadLocal()
+ {
+ NativeMethods.MemoryPoolHandle_ThreadLocal(out IntPtr handlePtr);
+ MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
+ return handle;
+ }
+
+ ///
+ /// Returns a MemoryPoolHandle pointing to a new thread-safe memory pool.
+ ///
+ /// Indicates whether the memory pool data
+ /// should be cleared when destroyed.This can be important when memory pools
+ /// are used to store private data.
+ public static MemoryPoolHandle New(bool clearOnDestruction = false)
+ {
+ NativeMethods.MemoryPoolHandle_New(clearOnDestruction, out IntPtr handlePtr);
+ MemoryPoolHandle handle = new MemoryPoolHandle(handlePtr);
+ return handle;
+ }
+
+ ///
+ /// Returns the number of different allocation sizes.
+ ///
+ ///
+ /// This function returns the number of different allocation sizes the memory
+ /// pool pointed to by the current MemoryPoolHandle has made. For example,
+ /// if the memory pool has only allocated two allocations of sizes 128 KB,
+ /// this function returns 1. If it has instead allocated one allocation of
+ /// size 64 KB and one of 128 KB, this functions returns 2.
+ ///
+ public ulong PoolCount
+ {
+ get
+ {
+ NativeMethods.MemoryPoolHandle_PoolCount(NativePtr, out ulong count);
+ return count;
+ }
+ }
+
+ ///
+ /// Returns the size of allocated memory.
+ ///
+ ///
+ /// This functions returns the total amount of memory (in bytes) allocated
+ /// by the memory pool pointed to by the current MemoryPoolHandle.
+ ///
+ public ulong AllocByteCount
+ {
+ get
+ {
+ NativeMethods.MemoryPoolHandle_AllocByteCount(NativePtr, out ulong count);
+ return count;
+ }
+ }
+
+ ///
+ /// Returns the number of MemoryPoolHandle objects sharing this memory pool.
+ ///
+ public long UseCount
+ {
+ get
+ {
+ NativeMethods.MemoryPoolHandle_UseCount(NativePtr, out long count);
+ return count;
+ }
+ }
+
+ ///
+ /// Returns whether the MemoryPoolHandle is initialized.
+ ///
+ public bool IsInitialized
+ {
+ get
+ {
+ NativeMethods.MemoryPoolHandle_IsInitialized(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Compares MemoryPoolHandles. This function returns whether the current
+ /// MemoryPoolHandle points to the same memory pool as a given MemoryPoolHandle.
+ ///
+ /// Object to compare to.
+ public override bool Equals(object obj)
+ {
+ MemoryPoolHandle other = obj as MemoryPoolHandle;
+ if (null == other)
+ return false;
+
+ NativeMethods.MemoryPoolHandle_Equals(NativePtr, other.NativePtr, out bool result);
+ return result;
+ }
+
+ ///
+ /// Get hash code for this MemoryPoolHandle
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.MemoryPoolHandle_Destroy(NativePtr);
+ }
+ }
+}
\ No newline at end of file
diff --git a/bigpiseal3.5.1/dotnet/src/Modulus.cs b/bigpiseal3.5.1/dotnet/src/Modulus.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0d3adff0ab9274a1a62c5ba215dfc35699d36ef7
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Modulus.cs
@@ -0,0 +1,548 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Research.SEAL
+{
+ /// Represent an integer modulus of up to 61 bits.
+ ///
+ ///
+ /// Represent an integer modulus of up to 61 bits. An instance of the Modulus
+ /// class represents a non-negative integer modulus up to 61 bits. In particular,
+ /// the encryption parameter PlainModulus, and the primes in CoeffModulus, are
+ /// represented by instances of Modulus. The purpose of this class is to
+ /// perform and store the pre-computation required by Barrett reduction.
+ ///
+ ///
+ /// In general, reading from Modulus is thread-safe as long as no other thread
+ /// is concurrently mutating it.
+ ///
+ ///
+ /// See EncryptionParameters for a description
+ /// of the encryption parameters.
+ public class Modulus : NativeObject,
+ IEquatable, IEquatable,
+ IComparable, IComparable
+ {
+ /// Creates a Modulus instance.
+ ///
+ /// Creates a Modulus instance. The value of the Modulus is set to 0.
+ ///
+ public Modulus()
+ {
+ NativeMethods.Modulus_Create(value: 0, smallModulus: out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ /// Creates a Modulus instance.
+ ///
+ /// Creates a Modulus instance. The value of the Modulus is set to
+ /// the given value.
+ ///
+ /// The integer modulus
+ /// if value is 1 or more than
+ /// 61 bits
+ public Modulus(ulong value)
+ {
+ NativeMethods.Modulus_Create(value, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ /// Creates a new Modulus by copying a given one.
+ /// The Modulus to copy from
+ /// if copy is null
+ public Modulus(Modulus copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.Modulus_Create(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a Modulus from a native pointer
+ ///
+ /// Pointer to the native Modulus
+ /// Whether this instance owns the native pointer
+ internal Modulus(IntPtr sm, bool owned = true)
+ : base(sm, owned)
+ {
+ }
+
+ /// Copies a given Modulus to the current one.
+ /// The Modulus to copy from
+ /// if assign is null
+ public void Set(Modulus assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.Modulus_Set(NativePtr, assign.NativePtr);
+ }
+
+ /// Sets the value of the Modulus.
+ /// The new integer modulus
+ /// if value is 1 or more than
+ /// 61 bits
+ public void Set(ulong value)
+ {
+ NativeMethods.Modulus_Set(NativePtr, value);
+ }
+
+ ///
+ /// Returns the significant bit count of the value of the current Modulus.
+ ///
+ public int BitCount
+ {
+ get
+ {
+ NativeMethods.Modulus_BitCount(NativePtr, out int result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns the size (in 64-bit words) of the value of the current Modulus.
+ ///
+ public ulong UInt64Count
+ {
+ get
+ {
+ NativeMethods.Modulus_UInt64Count(NativePtr, out ulong result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns the value of the current Modulus.
+ ///
+ public ulong Value
+ {
+ get
+ {
+ NativeMethods.Modulus_Value(NativePtr, out ulong result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns the Barrett ratio computed for the value of the current Modulus.
+ ///
+ ///
+ /// Returns the Barrett ratio computed for the value of the current Modulus.
+ /// The first two components of the Barrett ratio are the floor of 2^128/value,
+ /// and the third component is the remainder.
+ ///
+ public Tuple ConstRatio
+ {
+ get
+ {
+ ulong[] ratio = new ulong[3];
+ NativeMethods.Modulus_ConstRatio(NativePtr, length: (ulong)3, ratio: ratio);
+ return new Tuple(ratio[0], ratio[1], ratio[2]);
+ }
+ }
+
+ ///
+ /// Returns whether the value of the current Modulus is zero.
+ ///
+ public bool IsZero
+ {
+ get
+ {
+ NativeMethods.Modulus_IsZero(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns whether the value of the current Modulus is a prime number.
+ ///
+ public bool IsPrime
+ {
+ get
+ {
+ NativeMethods.Modulus_IsPrime(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns an upper bound on the size of the Modulus, as if it was
+ /// written to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.Modulus_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the Modulus to an output stream.
+ ///
+ /// Saves the Modulus to an output stream. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the Modulus to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.Modulus_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ ///
+ /// Loads a Modulus from an input stream overwriting the current
+ /// Modulus.
+ ///
+ /// The stream to load the Modulus from
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long Load(Stream stream)
+ {
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.Modulus_Load(NativePtr, outptr, size,
+ out outBytes),
+ stream);
+ }
+
+ ///
+ /// Returns a hash-code based on the value of the Modulus.
+ ///
+ public override int GetHashCode()
+ {
+ ulong[] arr = new ulong[1];
+ arr[0] = Value;
+ return Utilities.ComputeArrayHashCode(arr);
+ }
+
+ ///
+ /// Compares two Modulus instances.
+ ///
+ /// The value to compare against
+ public override bool Equals(object obj)
+ {
+ Modulus sm = obj as Modulus;
+ return Equals(sm);
+ }
+
+ /// Creates a Modulus instance.
+ ///
+ /// Creates a Modulus instance. The value of the Modulus is set to
+ /// the given value.
+ ///
+ /// The integer modulus
+ /// if value is 1 or more than 61 bits
+ public static explicit operator Modulus(ulong value)
+ {
+ Modulus sm = new Modulus(value);
+ return sm;
+ }
+
+ #region IEquatable methods
+
+ ///
+ /// Determines whether this instance equals another Modulus instance
+ ///
+ /// Instance to compare against
+ public bool Equals(Modulus other)
+ {
+ if (null == other)
+ return false;
+
+ NativeMethods.Modulus_Equals(NativePtr, other.NativePtr, out bool result);
+ return result;
+ }
+
+ #endregion
+
+ #region IEquatable methods
+
+ ///
+ /// Determines whether the value of this instance equals the given UInt64 value
+ ///
+ /// The value to compare against
+ public bool Equals(ulong other)
+ {
+ NativeMethods.Modulus_Equals(NativePtr, other, out bool result);
+ return result;
+ }
+
+ #endregion
+
+ #region IComparable methods
+
+ ///
+ /// Compares two Modulus instances.
+ ///
+ /// The Modulus to compare against
+ public int CompareTo(Modulus compare)
+ {
+ if (null == compare)
+ return 1;
+
+ return Value.CompareTo(compare.Value);
+ }
+
+ #endregion
+
+ #region IComparable methods
+
+ ///
+ /// Compares a Modulus value to an unsigned integer.
+ ///
+ /// The unsigned integer to compare against
+ public int CompareTo(ulong compare)
+ {
+ return Value.CompareTo(compare);
+ }
+
+ #endregion
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.Modulus_Destroy(NativePtr);
+ }
+ }
+
+ ///
+ /// Represents a standard security level according to the HomomorphicEncryption.org
+ /// security standard.
+ ///
+ ///
+ /// Represents a standard security level according to the HomomorphicEncryption.org
+ /// security standard. The value SecLevelType.None signals that no standard
+ /// security level should be imposed. The value SecLevelType.TC128 provides
+ /// a very high level of security and is the default security level enforced by
+ /// Microsoft SEAL when constructing a SEALContext object. Normal users should not
+ /// have to specify the security level explicitly anywhere.
+ ///
+ public enum SecLevelType : int
+ {
+ ///
+ /// No security level specified.
+ ///
+ None = 0,
+
+ ///
+ /// 128-bit security level according to HomomorphicEncryption.org standard.
+ ///
+ TC128 = 128,
+
+ ///
+ /// 192-bit security level according to HomomorphicEncryption.org standard.
+ ///
+ TC192 = 192,
+
+ ///
+ /// 256-bit security level according to HomomorphicEncryption.org standard.
+ ///
+ TC256 = 256
+ }
+
+ ///
+ /// This class contains static methods for creating a coefficient modulus easily.
+ ///
+ ///
+ ///
+ /// This class contains static methods for creating a coefficient modulus easily.
+ /// Note that while these functions take a SecLevelType argument, all security
+ /// guarantees are lost if the output is used with encryption parameters with
+ /// a mismatching value for the PolyModulusDegree.
+ ///
+ ///
+ /// The default value SecLevelType.TC128 provides a very high level of security
+ /// and is the default security level enforced by Microsoft SEAL when constructing
+ /// a SEALContext object. Normal users should not have to specify the security
+ /// level explicitly anywhere.
+ ///
+ ///
+ public static class CoeffModulus
+ {
+ ///
+ /// Returns the largest bit-length of the coefficient modulus, i.e., bit-length
+ /// of the product of the primes in the coefficient modulus, that guarantees
+ /// a given security level when using a given PolyModulusDegree, according
+ /// to the HomomorphicEncryption.org security standard.
+ ///
+ /// The value of the PolyModulusDegree
+ /// encryption parameter
+ /// The desired standard security level
+ static public int MaxBitCount(ulong polyModulusDegree, SecLevelType secLevel = SecLevelType.TC128)
+ {
+ NativeMethods.CoeffModulus_MaxBitCount(polyModulusDegree, (int)secLevel, out int result);
+ return result;
+ }
+
+ ///
+ /// Returns a default coefficient modulus for the BFV scheme that guarantees
+ /// a given security level when using a given PolyModulusDegree, according
+ /// to the HomomorphicEncryption.org security standard.
+ ///
+ ///
+ ///
+ /// Returns a default coefficient modulus for the BFV scheme that guarantees
+ /// a given security level when using a given PolyModulusDegree, according
+ /// to the HomomorphicEncryption.org security standard. Note that all security
+ /// guarantees are lost if the output is used with encryption parameters with
+ /// a mismatching value for the PolyModulusDegree.
+ ///
+ ///
+ /// The coefficient modulus returned by this function will not perform well
+ /// if used with the CKKS scheme.
+ ///
+ ///
+ /// The value of the PolyModulusDegree
+ /// encryption parameter
+ /// The desired standard security level
+ /// if polyModulusDegree is not
+ /// a power-of-two or is too large
+ /// if secLevel is SecLevelType.None
+ static public IEnumerable BFVDefault(
+ ulong polyModulusDegree, SecLevelType secLevel = SecLevelType.TC128)
+ {
+ List result = null;
+
+ ulong length = 0;
+ NativeMethods.CoeffModulus_BFVDefault(polyModulusDegree, (int)secLevel, ref length, null);
+
+ IntPtr[] coeffArray = new IntPtr[length];
+ NativeMethods.CoeffModulus_BFVDefault(polyModulusDegree, (int)secLevel, ref length, coeffArray);
+
+ result = new List(checked((int)length));
+ foreach (IntPtr sm in coeffArray)
+ {
+ result.Add(new Modulus(sm));
+ }
+
+ return result;
+ }
+
+ ///
+ /// Returns a custom coefficient modulus suitable for use with the specified
+ /// PolyModulusDegree.
+ ///
+ ///
+ /// Returns a custom coefficient modulus suitable for use with the specified
+ /// PolyModulusDegree.The return value will be a vector consisting of
+ /// Modulus elements representing distinct prime numbers of bit-lengths
+ /// as given in the bitSizes parameter. The bit sizes of the prime numbers
+ /// can be at most 60 bits.
+ ///
+ /// The value of the PolyModulusDegree
+ /// encryption parameter
+ /// The bit-lengths of the primes to be generated
+ /// if polyModulusDegree is not
+ /// a power-of-two or is too large
+ /// if bitSizes is too large or if its
+ /// elements are out of bounds
+ /// if not enough suitable primes could be found
+ static public IEnumerable Create(
+ ulong polyModulusDegree, IEnumerable bitSizes)
+ {
+ if (null == bitSizes)
+ throw new ArgumentNullException(nameof(bitSizes));
+
+ List result = null;
+
+ int[] bitSizesArr = bitSizes.ToArray();
+ int length = bitSizesArr.Length;
+
+ IntPtr[] coeffArray = new IntPtr[length];
+
+ NativeMethods.CoeffModulus_Create(polyModulusDegree, (ulong)length, bitSizesArr, coeffArray);
+
+ result = new List(length);
+ foreach (IntPtr sm in coeffArray)
+ {
+ result.Add(new Modulus(sm));
+ }
+
+ return result;
+ }
+ }
+
+ ///
+ /// This class contains static methods for creating a plaintext modulus easily.
+ ///
+ public static class PlainModulus
+ {
+ ///
+ /// Creates a prime number Modulus for use as PlainModulus encryption
+ /// parameter that supports batching with a given PolyModulusDegree.
+ ///
+ /// The value of the PolyModulusDegree
+ /// encryption parameter
+ /// The bit-length of the prime to be generated
+ /// if polyModulusDegree is not
+ /// a power-of-two or is too large
+ /// if bitSize is out of bounds
+ /// if a suitable prime could not be found
+ static public Modulus Batching(ulong polyModulusDegree, int bitSize)
+ {
+ return CoeffModulus.Create(
+ polyModulusDegree,
+ new int[] { bitSize }).First();
+ }
+
+ ///
+ /// Creates several prime number Modulus elements that can be used as
+ /// PlainModulus encryption parameters, each supporting batching with a given
+ /// PolyModulusDegree.
+ ///
+ /// The value of the PolyModulusDegree
+ /// encryption parameter
+ /// The bit-lengths of the primes to be generated
+ /// if polyModulusDegree is not
+ /// a power-of-two or is too large
+ /// if bitSizes is too large or if its
+ /// elements are out of bounds
+ /// if not enough suitable primes could be found
+ static public IEnumerable Batching(
+ ulong polyModulusDegree, IEnumerable bitSizes)
+ {
+ return CoeffModulus.Create(polyModulusDegree, bitSizes);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/NativeMethods.cs b/bigpiseal3.5.1/dotnet/src/NativeMethods.cs
new file mode 100644
index 0000000000000000000000000000000000000000..729579ff58191bb84fccaee29d8e0974b9a7d624
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/NativeMethods.cs
@@ -0,0 +1,1251 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Microsoft.Research.SEAL
+{
+ [Guid("A7AAD62F-3A48-4188-B6C3-523C294CFDAD")]
+ static class NativeMethods
+ {
+ private const string sealc = "sealc";
+
+ #region Version methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Version_Major(out byte value);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Version_Minor(out byte value);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Version_Patch(out byte value);
+
+ #endregion
+
+ #region BigUInt methods
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Create1", PreserveSig = false)]
+ internal static extern void BigUInt_Create(out IntPtr bigUInt);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Create2", PreserveSig = false)]
+ internal static extern void BigUInt_Create(int bitCount, out IntPtr bigUInt);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Create3", PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void BigUInt_Create(int bitCount, string hexString, out IntPtr bigUInt);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Create4", PreserveSig = false)]
+ internal static extern void BigUInt_Create(int bitCount, ulong value, out IntPtr bigUInt);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Create5", PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void BigUInt_Create(string hexString, out IntPtr bigUInt);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Create6", PreserveSig = false)]
+ internal static extern void BigUInt_Create(IntPtr copy, out IntPtr bigUInt);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_IsAlias(IntPtr thisptr, out bool isAlias);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_BitCount(IntPtr thisptr, out int bitCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_ByteCount(IntPtr thisptr, out ulong byteCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_UInt64Count(IntPtr thisptr, out ulong uint64Count);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_IsZero(IntPtr thisptr, out bool isZero);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_Get(IntPtr thisptr, ulong index, out byte value);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_GetU64(IntPtr thisptr, ulong index, out ulong value);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_GetSignificantBitCount(IntPtr thisptr, out int significantBitCount);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Set1", PreserveSig = false)]
+ internal static extern void BigUInt_Set(IntPtr thisptr, ulong index, byte value);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Set2", PreserveSig = false)]
+ internal static extern void BigUInt_Set(IntPtr thisptr, IntPtr assign);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Set3", PreserveSig = false)]
+ internal static extern void BigUInt_Set(IntPtr thisptr, ulong value);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_Set4", PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void BigUInt_Set(IntPtr thisptr, string assign);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_SetZero(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_Resize(IntPtr thisptr, int bitCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_Equals(IntPtr thisptr, IntPtr compare, out bool result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_CompareTo1", PreserveSig = false)]
+ internal static extern void BigUInt_CompareTo(IntPtr thisptr, IntPtr compare, out int result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_CompareTo2", PreserveSig = false)]
+ internal static extern void BigUInt_CompareTo(IntPtr thisptr, ulong compare, out int result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_DivideRemainder1", PreserveSig = false)]
+ internal static extern void BigUInt_DivideRemainder(IntPtr thisptr, IntPtr operand2, IntPtr remainder, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_DivideRemainder2", PreserveSig = false)]
+ internal static extern void BigUInt_DivideRemainder(IntPtr thisptr, ulong operand2, IntPtr remainder, out IntPtr result);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void BigUInt_ToString(IntPtr thisptr, StringBuilder outstr, out ulong length);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void BigUInt_ToDecimalString(IntPtr thisptr, StringBuilder outstr, out ulong length);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void BigUInt_DuplicateTo(IntPtr thisptr, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void BigUInt_DuplicateFrom(IntPtr thisptr, IntPtr value);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_ModuloInvert1", PreserveSig = false)]
+ internal static extern void BigUInt_ModuloInvert(IntPtr thisptr, IntPtr modulus, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_ModuloInvert2", PreserveSig = false)]
+ internal static extern void BigUInt_ModuloInvert(IntPtr thisptr, ulong modulus, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_TryModuloInvert1", PreserveSig = false)]
+ internal static extern void BigUInt_TryModuloInvert(IntPtr thisptr, IntPtr modulus, IntPtr inverse, out bool result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_TryModuloInvert2", PreserveSig = false)]
+ internal static extern void BigUInt_TryModuloInvert(IntPtr thisptr, ulong modulus, IntPtr inverse, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_OperatorNeg(IntPtr thisptr, out IntPtr result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_OperatorTilde(IntPtr thisptr, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorPlus1", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorPlus(IntPtr thisptr, IntPtr operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorPlus2", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorPlus(IntPtr thisptr, ulong operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorMinus1", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorMinus(IntPtr thisptr, IntPtr operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorMinus2", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorMinus(IntPtr thisptr, ulong operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorMult1", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorMult(IntPtr thisptr, IntPtr operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorMult2", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorMult(IntPtr thisptr, ulong operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorDiv1", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorDiv(IntPtr thisptr, IntPtr operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorDiv2", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorDiv(IntPtr thisptr, ulong operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorXor1", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorXor(IntPtr thisptr, IntPtr operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorXor2", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorXor(IntPtr thisptr, ulong operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorAnd1", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorAnd(IntPtr thisptr, IntPtr operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorAnd2", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorAnd(IntPtr thisptr, ulong operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorOr1", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorOr(IntPtr thisptr, IntPtr operand, out IntPtr result);
+
+ [DllImport(sealc, EntryPoint = "BigUInt_OperatorOr2", PreserveSig = false)]
+ internal static extern void BigUInt_OperatorOr(IntPtr thisptr, ulong operand, out IntPtr result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_OperatorShiftLeft(IntPtr thisptr, int shift, out IntPtr result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_OperatorShiftRight(IntPtr thisptr, int shift, out IntPtr result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_ToDouble(IntPtr thisptr, out double result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BigUInt_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region EncryptionParameterQualifiers methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_Create(IntPtr copy, out IntPtr epq);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_ParametersSet(IntPtr thisptr, out bool parametersSet);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_UsingFFT(IntPtr thisptr, out bool usingFFT);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_UsingNTT(IntPtr thisptr, out bool usingNTT);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_UsingBatching(IntPtr thisptr, out bool usingBatching);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_UsingFastPlainLift(IntPtr thisptr, out bool usingFastPlainLift);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_UsingDescendingModulusChain(IntPtr thisptr, out bool usingDescendingModulusChain);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EPQ_SecLevel(IntPtr thisptr, out int secLevel);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void EPQ_ParameterErrorName(IntPtr thisptr, StringBuilder outstr, out ulong length);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void EPQ_ParameterErrorMessage(IntPtr thisptr, StringBuilder outstr, out ulong length);
+
+ #endregion
+
+ #region Modulus methods
+
+ [DllImport(sealc, EntryPoint = "Modulus_Create1", PreserveSig = false)]
+ internal static extern void Modulus_Create(ulong value, out IntPtr smallModulus);
+
+ [DllImport(sealc, EntryPoint = "Modulus_Create2", PreserveSig = false)]
+ internal static extern void Modulus_Create(IntPtr copy, out IntPtr smallModulus);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_IsZero(IntPtr thisptr, out bool isZero);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_IsPrime(IntPtr thisptr, out bool isPrime);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_Value(IntPtr thisptr, out ulong value);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_BitCount(IntPtr thisptr, out int bitCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_UInt64Count(IntPtr thisptr, out ulong uint64Count);
+
+ [DllImport(sealc, EntryPoint = "Modulus_Set1", PreserveSig = false)]
+ internal static extern void Modulus_Set(IntPtr thisptr, IntPtr assign);
+
+ [DllImport(sealc, EntryPoint = "Modulus_Set2", PreserveSig = false)]
+ internal static extern void Modulus_Set(IntPtr thisptr, ulong value);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_ConstRatio(
+ IntPtr thisptr,
+ ulong length,
+ [MarshalAs(UnmanagedType.LPArray)] ulong[] ratio);
+
+ [DllImport(sealc, EntryPoint = "Modulus_Equals1", PreserveSig = false)]
+ internal static extern void Modulus_Equals(IntPtr thisptr, IntPtr other, out bool result);
+
+ [DllImport(sealc, EntryPoint = "Modulus_Equals2", PreserveSig = false)]
+ internal static extern void Modulus_Equals(IntPtr thisptr, ulong other, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Modulus_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region EncryptionParameters methods
+
+ [DllImport(sealc, EntryPoint = "EncParams_Create1", PreserveSig = false)]
+ internal static extern void EncParams_Create(byte scheme, out IntPtr encParams);
+
+ [DllImport(sealc, EntryPoint = "EncParams_Create2", PreserveSig = false)]
+ internal static extern void EncParams_Create(IntPtr copy, out IntPtr encParams);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_Set(IntPtr thisptr, IntPtr assign);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_GetPolyModulusDegree(IntPtr thisptr, out ulong polyModulusDegree);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_SetPolyModulusDegree(IntPtr thisptr, ulong polyModulusDegree);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_GetCoeffModulus(
+ IntPtr thisptr,
+ ref ulong length,
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffs);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_SetCoeffModulus(
+ IntPtr thisptr,
+ ulong length,
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffs);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_GetScheme(IntPtr thisptr, out byte scheme);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_GetParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_GetPlainModulus(IntPtr thisptr, out IntPtr plainModulus);
+
+ [DllImport(sealc, EntryPoint = "EncParams_SetPlainModulus1", PreserveSig = false)]
+ internal static extern void EncParams_SetPlainModulus(IntPtr thisptr, IntPtr plainModulus);
+
+ [DllImport(sealc, EntryPoint = "EncParams_SetPlainModulus2", PreserveSig = false)]
+ internal static extern void EncParams_SetPlainModulus(IntPtr thisptr, ulong plainModulus);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_Equals(IntPtr thisptr, IntPtr otherptr, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void EncParams_Load(IntPtr thisptr, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region CoeffModulus methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void CoeffModulus_MaxBitCount(ulong polyModulusDegree, int secLevel, out int bitCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void CoeffModulus_BFVDefault(
+ ulong polyModulusDegree,
+ int secLevel,
+ ref ulong length,
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffArray);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void CoeffModulus_Create(
+ ulong polyModulusDegree,
+ ulong length,
+ int[] bitSizes,
+ [MarshalAs(UnmanagedType.LPArray)] IntPtr[] coeffArray);
+
+ #endregion
+
+ #region SEALContext methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_Create(
+ IntPtr encryptionParams,
+ bool expandModChain,
+ int secLevel,
+ out IntPtr context);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_KeyParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_FirstParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_LastParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_ParametersSet(IntPtr thisptr, out bool paramsSet);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_ParameterErrorName(IntPtr thisptr, byte[] outstr, out ulong length);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_ParameterErrorMessage(IntPtr thisptr, byte[] outstr, out ulong length);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_KeyContextData(IntPtr thisptr, out IntPtr contextData);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_FirstContextData(IntPtr thisptr, out IntPtr contextData);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_LastContextData(IntPtr thisptr, out IntPtr contextData);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_GetContextData(IntPtr thisptr, ulong[] parmsId, out IntPtr contextData);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SEALContext_UsingKeyswitching(IntPtr thisptr, out bool usingKeySwitching);
+
+ #endregion
+
+ #region ContextData methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_TotalCoeffModulus(IntPtr thisptr, ref ulong count, ulong[] totalCoeffModulus);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_TotalCoeffModulusBitCount(IntPtr thisptr, out int bitCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_Parms(IntPtr thisptr, out IntPtr parms);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_Qualifiers(IntPtr thisptr, out IntPtr epq);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_CoeffDivPlainModulus(IntPtr thisptr, ref ulong count, ulong[] coefDivPlainMod);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_PlainUpperHalfThreshold(IntPtr thisptr, out ulong puht);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_PlainUpperHalfIncrement(IntPtr thisptr, ref ulong count, ulong[] puhi);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_UpperHalfThreshold(IntPtr thisptr, ref ulong count, ulong[] uht);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_UpperHalfIncrement(IntPtr thisptr, ref ulong count, ulong[] uhi);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_PrevContextData(IntPtr thisptr, out IntPtr prevContextData);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_NextContextData(IntPtr thisptr, out IntPtr nextContextData);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ContextData_ChainIndex(IntPtr thisptr, out ulong index);
+
+ #endregion
+
+ #region Evaluator methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Create(IntPtr sealContext, out IntPtr evaluator);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Negate(IntPtr thisptr, IntPtr encrypted, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Add(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_AddMany(IntPtr thisptr, ulong count, IntPtr[] encrypteds, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_AddPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Sub(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_SubPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Multiply(IntPtr thisptr, IntPtr encrypted1, IntPtr encrypted2, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_MultiplyMany(IntPtr thisptr, ulong count, IntPtr[] encrypteds, IntPtr relinKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_MultiplyPlain(IntPtr thisptr, IntPtr encrypted, IntPtr plain, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Square(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Relinearize(IntPtr thisptr, IntPtr encrypted, IntPtr relinKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchToNext1", PreserveSig = false)]
+ internal static extern void Evaluator_ModSwitchToNext(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchToNext2", PreserveSig = false)]
+ internal static extern void Evaluator_ModSwitchToNext(IntPtr thisptr, IntPtr plain, IntPtr destination);
+
+ [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchTo1", PreserveSig = false)]
+ internal static extern void Evaluator_ModSwitchTo(IntPtr thisptr, IntPtr encrypted, ulong[] parmsId, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "Evaluator_ModSwitchTo2", PreserveSig = false)]
+ internal static extern void Evaluator_ModSwitchTo(IntPtr thisptr, IntPtr plain, ulong[] parmsId, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_RescaleToNext(IntPtr thisptr, IntPtr encrypted, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_RescaleTo(IntPtr thisptr, IntPtr encrypted, ulong[] parmsId, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_Exponentiate(IntPtr thisptr, IntPtr encrypted, ulong exponent, IntPtr relinKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "Evaluator_TransformToNTT1", PreserveSig = false)]
+ internal static extern void Evaluator_TransformToNTT(IntPtr thisptr, IntPtr plain, ulong[] parmsId, IntPtr destinationNTT, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "Evaluator_TransformToNTT2", PreserveSig = false)]
+ internal static extern void Evaluator_TransformToNTT(IntPtr thisptr, IntPtr encrypted, IntPtr destinationNTT);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_TransformFromNTT(IntPtr thisptr, IntPtr encryptedNTT, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_ApplyGalois(IntPtr thisptr, IntPtr encrypted, uint galoisElt, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_RotateRows(IntPtr thisptr, IntPtr encrypted, int steps, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_RotateColumns(IntPtr thisptr, IntPtr encrypted, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_RotateVector(IntPtr thisptr, IntPtr encrypted, int steps, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_ComplexConjugate(IntPtr thisptr, IntPtr encrypted, IntPtr galoisKeys, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Evaluator_ContextUsingKeyswitching(IntPtr thisptr, out bool usingKeySwitching);
+
+ #endregion
+
+ #region Ciphertext methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Create1(IntPtr pool, out IntPtr cipher);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Create2(IntPtr copy, out IntPtr cipher);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Create3(IntPtr context, IntPtr pool, out IntPtr cipher);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Create4(IntPtr context, ulong[] parmsId, IntPtr pool, out IntPtr cipher);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Create5(IntPtr context, ulong[] parmsId, ulong capacity, IntPtr pool, out IntPtr cipher);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_Reserve1", PreserveSig = false)]
+ internal static extern void Ciphertext_Reserve(IntPtr thisptr, IntPtr context, ulong[] parmsId, ulong sizeCapacity);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_Reserve2", PreserveSig = false)]
+ internal static extern void Ciphertext_Reserve(IntPtr thisptr, IntPtr context, ulong sizeCapacity);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_Reserve3", PreserveSig = false)]
+ internal static extern void Ciphertext_Reserve(IntPtr thisptr, ulong sizeCapacity);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Set(IntPtr thisptr, IntPtr assign);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_UInt64Count(IntPtr thisptr, out ulong uint64Count);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_UInt64CountCapacity(IntPtr thisptr, out ulong uint64CountCapacity);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Size(IntPtr thisptr, out ulong size);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_SizeCapacity(IntPtr thisptr, out ulong sizeCapacity);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_PolyModulusDegree(IntPtr thisptr, out ulong polyModulusDegree);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_CoeffModulusSize(IntPtr thisptr, out ulong coeffModCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_ParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_SetParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_Resize1", PreserveSig = false)]
+ internal static extern void Ciphertext_Resize(IntPtr thisptr, IntPtr context, ulong[] parms_id, ulong size);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_Resize2", PreserveSig = false)]
+ internal static extern void Ciphertext_Resize(IntPtr thisptr, IntPtr context, ulong size);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_Resize3", PreserveSig = false)]
+ internal static extern void Ciphertext_Resize(IntPtr thisptr, ulong size);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_Resize4", PreserveSig = false)]
+ internal static extern void Ciphertext_Resize(IntPtr thisptr, ulong size, ulong polyModulusDegree, ulong coeffModCount);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_GetDataAt1", PreserveSig = false)]
+ internal static extern void Ciphertext_GetDataAt(IntPtr thisptr, ulong index, out ulong data);
+
+ [DllImport(sealc, EntryPoint = "Ciphertext_GetDataAt2", PreserveSig = false)]
+ internal static extern void Ciphertext_GetDataAt(IntPtr thisptr, ulong polyIndex, ulong coeffIndex, out ulong data);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_SetDataAt(IntPtr thisptr, ulong index, ulong value);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_IsNTTForm(IntPtr thisptr, out bool isNTTForm);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_SetIsNTTForm(IntPtr thisptr, bool isNTTForm);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Scale(IntPtr thisptr, out double scale);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_SetScale(IntPtr thisptr, double scale);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Release(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_IsTransparent(IntPtr thisptr, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Pool(IntPtr thisptr, out IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Ciphertext_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region Plaintext methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Create1(IntPtr memoryPoolHandle, out IntPtr plainText);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Create2(ulong coeffCount, IntPtr memoryPoolHandle, out IntPtr plainText);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Create3(ulong capacity, ulong coeffCount, IntPtr memoryPoolHandle, out IntPtr plainText);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void Plaintext_Create4(string hexPoly, IntPtr memoryPoolHandle, out IntPtr plainText);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Create5(IntPtr copy, out IntPtr plainText);
+
+ [DllImport(sealc, EntryPoint = "Plaintext_Set1", PreserveSig = false)]
+ internal static extern void Plaintext_Set(IntPtr thisptr, IntPtr assign);
+
+ [DllImport(sealc, EntryPoint = "Plaintext_Set2", PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void Plaintext_Set(IntPtr thisptr, string hexPoly);
+
+ [DllImport(sealc, EntryPoint = "Plaintext_Set3", PreserveSig = false)]
+ internal static extern void Plaintext_Set(IntPtr thisptr, ulong constCoeff);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_CoeffCount(IntPtr thisptr, out ulong coeffCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_CoeffAt(IntPtr thisptr, ulong index, out ulong coeff);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_SetCoeffAt(IntPtr thisptr, ulong index, ulong value);
+
+ [DllImport(sealc, PreserveSig = false, CharSet = CharSet.Ansi)]
+ internal static extern void Plaintext_ToString(IntPtr thisptr, StringBuilder outstr, out ulong length);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_IsNTTForm(IntPtr thisptr, out bool isNTTForm);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_IsZero(IntPtr thisptr, out bool isZero);
+
+ [DllImport(sealc, EntryPoint = "Plaintext_SetZero1", PreserveSig = false)]
+ internal static extern void Plaintext_SetZero(IntPtr thisptr);
+
+ [DllImport(sealc, EntryPoint = "Plaintext_SetZero2", PreserveSig = false)]
+ internal static extern void Plaintext_SetZero(IntPtr thisptr, ulong startCoeff);
+
+ [DllImport(sealc, EntryPoint = "Plaintext_SetZero3", PreserveSig = false)]
+ internal static extern void Plaintext_SetZero(IntPtr thisptr, ulong startCoeff, ulong length);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_GetParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_SetParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Reserve(IntPtr thisptr, ulong capacity);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Resize(IntPtr thisptr, ulong coeffCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_ShrinkToFit(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Release(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Capacity(IntPtr thisptr, out ulong capacity);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_UInt64Count(IntPtr thisptr, out ulong uint64Count);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_UInt64CountCapacity(IntPtr thisptr, out ulong uint64CountCapacity);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_SignificantCoeffCount(IntPtr thisptr, out ulong significantCoeffCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_NonZeroCoeffCount(IntPtr thisptr, out ulong nonZeroCoeffCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Scale(IntPtr thisptr, out double scale);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_SetScale(IntPtr thisptr, double scale);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Equals(IntPtr thisptr, IntPtr otherptr, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_SwapData(IntPtr thisptr, ulong count, ulong[] newData);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Pool(IntPtr thisptr, out IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Plaintext_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region KSwitchKeys methods
+
+ [DllImport(sealc, EntryPoint = "KSwitchKeys_Create1", PreserveSig = false)]
+ internal static extern void KSwitchKeys_Create(out IntPtr kswitchKeys);
+
+ [DllImport(sealc, EntryPoint = "KSwitchKeys_Create2", PreserveSig = false)]
+ internal static extern void KSwitchKeys_Create(IntPtr copy, out IntPtr kswitchKeys);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_Set(IntPtr thisptr, IntPtr assignptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_Size(IntPtr thisptr, out ulong size);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_ClearDataAndReserve(IntPtr thisptr, ulong size);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_RawSize(IntPtr thisptr, out ulong keyCount);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_GetKeyList(IntPtr thisptr, ulong index, ref ulong count, IntPtr[] key_list);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_AddKeyList(IntPtr thisptr, ulong count, IntPtr[] key_list);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_GetParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_SetParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_Pool(IntPtr thisptr, out IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KSwitchKeys_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region GaloisKeys methods
+
+ [DllImport(sealc, EntryPoint = "GaloisKeys_GetIndex", PreserveSig = false)]
+ internal static extern void GaloisKeys_GetIndex(uint galoisElt, out ulong index);
+
+ #endregion
+
+ #region KeyGenerator methods
+
+ [DllImport(sealc, EntryPoint = "KeyGenerator_Create1", PreserveSig = false)]
+ internal static extern void KeyGenerator_Create(IntPtr sealContext, out IntPtr keyGenerator);
+
+ [DllImport(sealc, EntryPoint = "KeyGenerator_Create2", PreserveSig = false)]
+ internal static extern void KeyGenerator_Create(IntPtr sealContext, IntPtr secretKey, out IntPtr keyGenerator);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KeyGenerator_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KeyGenerator_RelinKeys(IntPtr thisptr, bool save_seed, out IntPtr relin_keys);
+
+ [DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysAll", PreserveSig = false)]
+ internal static extern void KeyGenerator_GaloisKeysAll(IntPtr thisptr, bool save_seed, out IntPtr galoisKeys);
+
+ [DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysFromElts", PreserveSig = false)]
+ internal static extern void KeyGenerator_GaloisKeysFromElts(IntPtr thisptr, ulong count, uint[] galoisElts, bool save_seed, out IntPtr galoisKeys);
+
+ [DllImport(sealc, EntryPoint = "KeyGenerator_GaloisKeysFromSteps", PreserveSig = false)]
+ internal static extern void KeyGenerator_GaloisKeysFromSteps(IntPtr thisptr, ulong count, int[] steps, bool save_seed, out IntPtr galoisKeys);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KeyGenerator_PublicKey(IntPtr thisptr, out IntPtr publicKey);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KeyGenerator_SecretKey(IntPtr thisptr, out IntPtr secretKey);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void KeyGenerator_ContextUsingKeyswitching(IntPtr thisptr, out bool result);
+
+ #endregion
+
+ #region RelinKeys methods
+
+ [DllImport(sealc, EntryPoint = "RelinKeys_GetIndex", PreserveSig = false)]
+ internal static extern void RelinKeys_GetIndex(ulong keyPower, out ulong index);
+
+ #endregion
+
+ #region PublicKey methods
+
+ [DllImport(sealc, EntryPoint = "PublicKey_Create1", PreserveSig = false)]
+ internal static extern void PublicKey_Create(out IntPtr publicKey);
+
+ [DllImport(sealc, EntryPoint = "PublicKey_Create2", PreserveSig = false)]
+ internal static extern void PublicKey_Create(IntPtr copy, out IntPtr publicKey);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_Set(IntPtr thisptr, IntPtr assign);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_Data(IntPtr thisptr, out IntPtr data);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_ParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_Pool(IntPtr thisptr, out IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void PublicKey_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region SecretKey methods
+
+ [DllImport(sealc, EntryPoint = "SecretKey_Create1", PreserveSig = false)]
+ internal static extern void SecretKey_Create(out IntPtr secretKey);
+
+ [DllImport(sealc, EntryPoint = "SecretKey_Create2", PreserveSig = false)]
+ internal static extern void SecretKey_Create(IntPtr copy, out IntPtr secretKey);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_Set(IntPtr thisptr, IntPtr assign);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_Data(IntPtr thisptr, out IntPtr data);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_ParmsId(IntPtr thisptr, ulong[] parmsId);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_Pool(IntPtr thisptr, out IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_SaveSize(IntPtr thisptr, byte comprMode, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_Save(IntPtr thisptr, byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_Load(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void SecretKey_UnsafeLoad(IntPtr thisptr, IntPtr context, byte[] inptr, ulong size, out long inBytes);
+
+ #endregion
+
+ #region MemoryManager methods
+
+ [DllImport(sealc, EntryPoint = "MemoryManager_GetPool1", PreserveSig = false)]
+ internal static extern void MemoryManager_GetPool(int profOpt, bool clearOnDestruction, out IntPtr handle);
+
+ [DllImport(sealc, EntryPoint = "MemoryManager_GetPool2", PreserveSig = false)]
+ internal static extern void MemoryManager_GetPool(out IntPtr handle);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryManager_SwitchProfile(IntPtr newProfile);
+
+ #endregion
+
+ #region MMProf methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MMProf_CreateGlobal(out IntPtr profile);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MMProf_CreateFixed(IntPtr pool, out IntPtr profile);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MMProf_CreateNew(out IntPtr profile);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MMProf_CreateThreadLocal(out IntPtr profile);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MMProf_GetPool(IntPtr thisptr, out IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MMProf_Destroy(IntPtr thisptr);
+
+ #endregion
+
+ #region MemoryPoolHandle methods
+
+ [DllImport(sealc, EntryPoint = "MemoryPoolHandle_Create1", PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_Create(out IntPtr handlePtr);
+
+ [DllImport(sealc, EntryPoint = "MemoryPoolHandle_Create2", PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_Create(IntPtr other, out IntPtr handlePtr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_Set(IntPtr thisptr, IntPtr assignptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_Global(out IntPtr handlePtr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_ThreadLocal(out IntPtr handlePtr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_New(bool clearOnDestruction, out IntPtr handlePtr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_PoolCount(IntPtr thisptr, out ulong count);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_AllocByteCount(IntPtr thisptr, out ulong count);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_UseCount(IntPtr thisptr, out long count);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_IsInitialized(IntPtr thisptr, out bool initialized);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void MemoryPoolHandle_Equals(IntPtr thisptr, IntPtr otherptr, out bool result);
+
+ #endregion
+
+ #region Encryptor methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_Create(IntPtr context, IntPtr publicKey, IntPtr secretKey, out IntPtr encryptor);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_SetPublicKey(IntPtr thisptr, IntPtr publicKey);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_SetSecretKey(IntPtr thisptr, IntPtr secretKey);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_Encrypt(IntPtr thisptr, IntPtr plaintext, IntPtr destination, IntPtr poolHandle);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_EncryptZero1(IntPtr thisptr, ulong[] parmsId, IntPtr destination, IntPtr poolHandle);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_EncryptZero2(IntPtr thisptr, IntPtr destination, IntPtr poolHandle);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_EncryptSymmetric(IntPtr thisptr, IntPtr plaintext, bool save_seed, IntPtr destination, IntPtr poolHandle);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_EncryptZeroSymmetric1(IntPtr thisptr, ulong[] parmsId, bool save_seed, IntPtr destination, IntPtr poolHandle);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_EncryptZeroSymmetric2(IntPtr thisptr, bool save_seed, IntPtr destination, IntPtr poolHandle);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Encryptor_Destroy(IntPtr thisptr);
+
+ #endregion
+
+ #region Decryptor methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Decryptor_Create(IntPtr context, IntPtr secretKey, out IntPtr decryptor);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Decryptor_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Decryptor_Decrypt(IntPtr thisptr, IntPtr encrypted, IntPtr destination);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Decryptor_InvariantNoiseBudget(IntPtr thisptr, IntPtr encrypted, out int invariantNoiseBudget);
+
+ #endregion
+
+ #region CKKSEncoder methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void CKKSEncoder_Create(IntPtr context, out IntPtr ckksEncoder);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void CKKSEncoder_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode1", PreserveSig = false)]
+ internal static extern void CKKSEncoder_EncodeDouble(IntPtr thisptr, ulong valueCount, double[] values, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode2", PreserveSig = false)]
+ internal static extern void CKKSEncoder_EncodeComplex(IntPtr thisptr, ulong valueCount, double[] values, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode3", PreserveSig = false)]
+ internal static extern void CKKSEncoder_Encode(IntPtr thisptr, double value, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode4", PreserveSig = false)]
+ internal static extern void CKKSEncoder_Encode(IntPtr thisptr, double valueRe, double valueIm, ulong[] parms_id, double scale, IntPtr destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "CKKSEncoder_Encode5", PreserveSig = false)]
+ internal static extern void CKKSEncoder_Encode(IntPtr thisptr, long value, ulong[] parms_id, IntPtr destination);
+
+ [DllImport(sealc, EntryPoint = "CKKSEncoder_Decode1", PreserveSig = false)]
+ internal static extern void CKKSEncoder_DecodeDouble(IntPtr thisptr, IntPtr plain, ref ulong valueCount, double[] values, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "CKKSEncoder_Decode2", PreserveSig = false)]
+ internal static extern void CKKSEncoder_DecodeComplex(IntPtr thisptr, IntPtr plain, ref ulong valueCount, double[] values, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void CKKSEncoder_SlotCount(IntPtr thisptr, out ulong slotCount);
+
+ #endregion
+
+ #region BatchEncoder methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BatchEncoder_Create(IntPtr context, out IntPtr batchEncoder);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BatchEncoder_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, EntryPoint = "BatchEncoder_Encode1", PreserveSig = false)]
+ internal static extern void BatchEncoder_Encode(IntPtr thisptr, ulong count, ulong[] values, IntPtr destination);
+
+ [DllImport(sealc, EntryPoint = "BatchEncoder_Encode2", PreserveSig = false)]
+ internal static extern void BatchEncoder_Encode(IntPtr thisptr, ulong count, long[] values, IntPtr destination);
+
+ [DllImport(sealc, EntryPoint = "BatchEncoder_Encode3", PreserveSig = false)]
+ internal static extern void BatchEncoder_Encode(IntPtr thisptr, IntPtr plain, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "BatchEncoder_Decode1", PreserveSig = false)]
+ internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, ref ulong count, ulong[] destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "BatchEncoder_Decode2", PreserveSig = false)]
+ internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, ref ulong count, long[] destination, IntPtr pool);
+
+ [DllImport(sealc, EntryPoint = "BatchEncoder_Decode3", PreserveSig = false)]
+ internal static extern void BatchEncoder_Decode(IntPtr thisptr, IntPtr plain, IntPtr pool);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void BatchEncoder_GetSlotCount(IntPtr thisptr, out ulong slotCount);
+
+ #endregion
+
+ #region IntegerEncoder methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_Create(IntPtr context, out IntPtr encoder);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_Destroy(IntPtr thisptr);
+
+ [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode1", PreserveSig = false)]
+ internal static extern void IntegerEncoder_Encode(IntPtr thisptr, int value, IntPtr plain);
+
+ [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode2", PreserveSig = false)]
+ internal static extern void IntegerEncoder_Encode(IntPtr thisptr, uint value, IntPtr plain);
+
+ [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode3", PreserveSig = false)]
+ internal static extern void IntegerEncoder_Encode(IntPtr thisptr, ulong value, IntPtr plain);
+
+ [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode4", PreserveSig = false)]
+ internal static extern void IntegerEncoder_Encode(IntPtr thisptr, long value, IntPtr plain);
+
+ [DllImport(sealc, EntryPoint = "IntegerEncoder_Encode5", PreserveSig = false)]
+ internal static extern void IntegerEncoder_Encode(IntPtr thisptr, IntPtr bigUInt, IntPtr plain);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_DecodeUInt32(IntPtr thisptr, IntPtr plain, out uint result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_DecodeUInt64(IntPtr thisptr, IntPtr plain, out ulong result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_DecodeInt32(IntPtr thisptr, IntPtr plain, out int result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_DecodeInt64(IntPtr thisptr, IntPtr plain, out long result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_DecodeBigUInt(IntPtr thisptr, IntPtr plain, out IntPtr bigUInt);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void IntegerEncoder_PlainModulus(IntPtr thisptr, out IntPtr smallModulus);
+
+ #endregion
+
+ #region ValCheck methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ValCheck_Plaintext_IsValidFor(IntPtr plaintext, IntPtr context, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ValCheck_Ciphertext_IsValidFor(IntPtr ciphertext, IntPtr context, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ValCheck_SecretKey_IsValidFor(IntPtr secretKey, IntPtr context, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ValCheck_PublicKey_IsValidFor(IntPtr publicKey, IntPtr context, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ValCheck_KSwitchKeys_IsValidFor(IntPtr kswitchKeys, IntPtr context, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ValCheck_RelinKeys_IsValidFor(IntPtr relinKeys, IntPtr context, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void ValCheck_GaloisKeys_IsValidFor(IntPtr galoisKeys, IntPtr context, out bool result);
+
+ #endregion
+
+ #region Serialization methods
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Serialization_SEALMagic(out ushort result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Serialization_SEALHeaderSize(out byte result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Serialization_IsSupportedComprMode(byte comprMode, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Serialization_ComprModeDefault(out byte result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Serialization_IsCompatibleVersion(byte[] headerptr, ulong size, out bool result);
+
+ [DllImport(sealc, PreserveSig = false)]
+ internal static extern void Serialization_IsValidHeader(byte[] headerptr, ulong size, out bool result);
+
+ #endregion
+
+ public static class Errors
+ {
+ public const uint NoError = 0;
+ public const uint InsufficientBuffer = 122;
+ public const uint BadArguments = 160;
+ public const uint InvalidIndex = 1413;
+ public const uint InvalidOperation = 4317;
+ public const uint HRPointer = 0x80004003;
+ public const uint HRInvalidIndex = 0x80070585;
+ public const uint HRInvalidOperation = 0x800710DD;
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/ParmsId.cs b/bigpiseal3.5.1/dotnet/src/ParmsId.cs
new file mode 100644
index 0000000000000000000000000000000000000000..223444d9abed2b8e1bf54720bcbdb793a22d1540
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/ParmsId.cs
@@ -0,0 +1,159 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Text;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Identify a set of Encryption Parameters
+ ///
+ public class ParmsId : IEquatable
+ {
+ ///
+ /// Create an instance of ParmsId
+ ///
+ public ParmsId()
+ {
+ }
+
+ ///
+ /// Create an instance of ParmsId by copying other instance
+ ///
+ /// Instance to copy
+ public ParmsId(ParmsId other)
+ {
+ if (null == other)
+ throw new ArgumentNullException(nameof(other));
+ CopyId(this, other.Block);
+ }
+
+ ///
+ /// Create an instance of ParmsId by copying the input array
+ ///
+ /// Array to copy
+ private ParmsId(ulong[] id)
+ {
+ if (null == id)
+ throw new ArgumentNullException(nameof(id));
+ if (id.Length != ULongCount)
+ throw new ArgumentException($"id length should be {ULongCount}");
+
+ CopyId(this, id);
+ }
+
+ ///
+ /// Array that contains the Params Id hash block
+ ///
+ public ulong[] Block { get; } = new ulong[4] { 0, 0, 0, 0 };
+
+ ///
+ /// Copy an input array to the ParmsId hash block
+ ///
+ private static void CopyId(ParmsId dest, ulong[] src)
+ {
+ int idx = 0;
+ foreach (ulong ul in src)
+ {
+ dest.Block[idx++] = ul;
+ }
+ }
+
+ ///
+ /// Convert ParmsId to a string representation.
+ ///
+ public override string ToString()
+ {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < ULongCount; i++)
+ {
+ byte[] bytes = BitConverter.GetBytes(Block[i]);
+ for (int b = bytes.Length - 1; b >= 0; b--)
+ {
+ result.Append(BitConverter.ToString(bytes, b, length: 1));
+ }
+ if (i < (ULongCount - 1))
+ result.Append(" ");
+ }
+
+ return result.ToString();
+ }
+
+ ///
+ /// Hash code for this object
+ ///
+ public override int GetHashCode()
+ {
+ return Utilities.ComputeArrayHashCode(Block);
+ }
+
+ ///
+ /// Whether the input object is equivalent to this object
+ ///
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as ParmsId);
+ }
+
+ ///
+ /// Whether the input object is equivalent to this object
+ ///
+ public bool Equals(ParmsId other)
+ {
+ if (null == other)
+ return false;
+
+ for (int i = 0; i < ULongCount; i++)
+ {
+ if (Block[i] != other.Block[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Return whether parms1 equals parms2.
+ ///
+ public static bool operator ==(ParmsId parms1, ParmsId parms2)
+ {
+ object obj1 = parms1 as object;
+ object obj2 = parms2 as object;
+
+ if (null == obj1 && null == obj2)
+ return true;
+ if (null == obj1)
+ return false;
+
+ return parms1.Equals(parms2);
+ }
+
+ ///
+ /// Return whether parms1 does not equal parms2.
+ ///
+ public static bool operator !=(ParmsId parms1, ParmsId parms2)
+ {
+ object obj1 = parms1 as object;
+ object obj2 = parms2 as object;
+
+ if (null == obj1 && null == obj2)
+ return false;
+ if (null == obj1)
+ return true;
+
+ return !parms1.Equals(parms2);
+ }
+
+ ///
+ /// ParmsId with a Zero hash block
+ ///
+ public static ParmsId Zero = new ParmsId(new ulong[4] { 0, 0, 0, 0 });
+
+ ///
+ /// Number of elements in the hash block array
+ ///
+ private const int ULongCount = 4;
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/Plaintext.cs b/bigpiseal3.5.1/dotnet/src/Plaintext.cs
new file mode 100644
index 0000000000000000000000000000000000000000..210b5dd679a1e0f106e7221ef5c8acb85c148575
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Plaintext.cs
@@ -0,0 +1,685 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Class to store a plaintext element.
+ ///
+ ///
+ ///
+ /// Class to store a plaintext element. The data for the plaintext is
+ /// a polynomial with coefficients modulo the plaintext modulus. The degree
+ /// of the plaintext polynomial must be one less than the degree of the
+ /// polynomial modulus. The backing array always allocates one 64-bit word
+ /// per each coefficient of the polynomial.
+ ///
+ ///
+ /// Memory Management
+ /// The coefficient count of a plaintext refers to the number of word-size
+ /// coefficients in the plaintext, whereas its capacity refers to the number
+ /// of word-size coefficients that fit in the current memory allocation. In
+ /// high-performance applications unnecessary re-allocations should be avoided
+ /// by reserving enough memory for the plaintext to begin with either by
+ /// providing the desired capacity to the constructor as an extra argument, or
+ /// by calling the reserve function at any time.
+ ///
+ /// When the scheme is SchemeType.BFV each coefficient of a plaintext is
+ /// a 64-bit word, but when the scheme is SchemeType.CKKS the plaintext is
+ /// by default stored in an NTT transformed form with respect to each of the
+ /// primes in the coefficient modulus. Thus, the size of the allocation that
+ /// is needed is the size of the coefficient modulus (number of primes) times
+ /// the degree of the polynomial modulus. In addition, a valid CKKS plaintext
+ /// will also store the ParmsId for the corresponding encryption parameters.
+ ///
+ ///
+ /// Thread Safety
+ /// In general, reading from plaintext is thread-safe as long as no other
+ /// thread is concurrently mutating it. This is due to the underlying data
+ /// structure storing the plaintext not being thread-safe.
+ ///
+ ///
+ /// See Ciphertext for the class that stores ciphertexts.
+ public class Plaintext : NativeObject, IEquatable
+ {
+ ///
+ /// Constructs an empty plaintext allocating no memory.
+ ///
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if pool is uninitialized
+ public Plaintext(MemoryPoolHandle pool = null)
+ {
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+
+ NativeMethods.Plaintext_Create1(poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs a plaintext representing a constant polynomial 0. The
+ /// coefficient count of the polynomial is set to the given value. The
+ /// capacity is set to the same value.
+ ///
+ /// The number of (zeroed) coefficients in the
+ /// plaintext polynomial
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if coeffCount is negative
+ /// if pool is uninitialized
+ public Plaintext(ulong coeffCount, MemoryPoolHandle pool = null)
+ {
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+
+ NativeMethods.Plaintext_Create2(coeffCount, poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs a plaintext representing a constant polynomial 0. The
+ /// coefficient count of the polynomial and the capacity are set to the
+ /// given values.
+ ///
+ /// The capacity
+ /// The number of (zeroed) coefficients in the
+ /// plaintext polynomial
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if capacity is less than coeffCount
+ /// if coeffCount is negative
+ /// if pool is uninitialized
+ public Plaintext(ulong capacity, ulong coeffCount, MemoryPoolHandle pool = null)
+ {
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+
+ NativeMethods.Plaintext_Create3(capacity, coeffCount, poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs a plaintext from a given hexadecimal string describing the
+ /// plaintext polynomial.
+ ///
+ ///
+ /// The string description of the polynomial must adhere to the format
+ /// returned by ToString(), which is of the form "7FFx^3 + 1x^1 + 3"
+ /// and summarized by the following
+ /// rules:
+ /// 1. Terms are listed in order of strictly decreasing exponent
+ /// 2. Coefficient values are non-negative and in hexadecimal format (upper
+ /// and lower case letters are both supported)
+ /// 3. Exponents are positive and in decimal format
+ /// 4. Zero coefficient terms (including the constant term) may be (but do
+ /// not have to be) omitted
+ /// 5. Term with the exponent value of one must be exactly written as x^1
+ /// 6. Term with the exponent value of zero (the constant term) must be written
+ /// as just a hexadecimal number without exponent
+ /// 7. Terms must be separated by exactly [space]+[space] and minus is not
+ /// allowed
+ /// 8. Other than the +, no other terms should have whitespace
+ ///
+ /// The formatted polynomial string specifying the plaintext
+ /// polynomial
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if hexPoly is null
+ /// if hexPoly does not adhere to the expected
+ /// format
+ /// if pool is uninitialized
+ public Plaintext(string hexPoly, MemoryPoolHandle pool = null)
+ {
+ if (null == hexPoly)
+ throw new ArgumentNullException(nameof(hexPoly));
+
+ IntPtr poolPtr = pool?.NativePtr ?? IntPtr.Zero;
+
+ NativeMethods.Plaintext_Create4(hexPoly, poolPtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs a new plaintext by copying a given one.
+ ///
+ /// The plaintext to copy from
+ /// if copy is null
+ public Plaintext(Plaintext copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.Plaintext_Create5(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Constructs a new plaintext by copying a given one.
+ ///
+ /// The plaintext to copy from
+ /// The MemoryPoolHandle pointing to a valid memory pool
+ /// if either copy or pool are null
+ /// if pool is uninitialized
+ public Plaintext(Plaintext copy, MemoryPoolHandle pool) : this(pool)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ Set(copy);
+ }
+
+ ///
+ /// Constructs a plaintext by initializing it with a pointer to a native object.
+ ///
+ /// Pointer to native Plaintext object
+ /// Whether this instance owns the native pointer
+ internal Plaintext(IntPtr plaintextPtr, bool owned = true)
+ : base(plaintextPtr, owned)
+ {
+ }
+
+ ///
+ /// Allocates enough memory to accommodate the backing array of a plaintext
+ /// with given capacity.
+ ///
+ /// The capacity
+ /// if the plaintext is NTT transformed
+ public void Reserve(ulong capacity)
+ {
+ NativeMethods.Plaintext_Reserve(NativePtr, capacity);
+ }
+
+ ///
+ /// Allocates enough memory to accommodate the backing array of the current
+ /// plaintext and copies it over to the new location. This function is meant
+ /// to reduce the memory use of the plaintext to smallest possible and can be
+ /// particularly important after modulus switching.
+ ///
+ public void ShrinkToFit()
+ {
+ NativeMethods.Plaintext_ShrinkToFit(NativePtr);
+ }
+
+ ///
+ /// Resets the plaintext. This function releases any memory allocated by the
+ /// plaintext, returning it to the memory pool.
+ ///
+ public void Release()
+ {
+ NativeMethods.Plaintext_Release(NativePtr);
+ }
+
+ ///
+ /// Resizes the plaintext to have a given coefficient count. The plaintext
+ /// is automatically reallocated if the new coefficient count does not fit in
+ /// the current capacity.
+ ///
+ /// The number of coefficients in the plaintext
+ /// polynomial
+ /// if the plaintext is NTT transformed
+ public void Resize(ulong coeffCount)
+ {
+ NativeMethods.Plaintext_Resize(NativePtr, coeffCount);
+ }
+
+ ///
+ /// Copies a given plaintext to the current one.
+ ///
+ ///
+ /// The plaintext to copy from
+ /// if assign is null
+ public void Set(Plaintext assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.Plaintext_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Sets the value of the current plaintext to the polynomial represented by the a given hexadecimal string.
+ ///
+ ///
+ ///
+ ///
+ /// Sets the value of the current plaintext to the polynomial represented by the a given hexadecimal string.
+ ///
+ ///
+ /// The string description of the polynomial must adhere to the format returned by ,
+ /// which is of the form "7FFx^3 + 1x^1 + 3" and summarized by the following rules:
+ ///
+ /// - Terms are listed in order of strictly decreasing exponent
+ /// - Coefficient values are non-negative and in hexadecimal format (upper and lower case letters are both supported)
+ /// - Exponents are positive and in decimal format
+ /// - Zero coefficient terms (including the constant term) may be (but do not have to be) omitted
+ /// - Term with the exponent value of one is written as x^1
+ /// - Term with the exponent value of zero (the constant term) is written as just a hexadecimal number without x or exponent
+ /// - Terms are separated exactly by <space>+<space>
+ /// - Other than the +, no other terms have whitespace
+ ///
+ ///
+ ///
+ /// The formatted polynomial string specifying the plaintext polynomial
+ /// if hexPoly does not adhere to the expected format
+ /// if the coefficients of hexPoly are too wide
+ /// if hexPoly is null
+ public void Set(string hexPoly)
+ {
+ if (null == hexPoly)
+ throw new ArgumentNullException(nameof(hexPoly));
+
+ NativeMethods.Plaintext_Set(NativePtr, hexPoly);
+ }
+
+ ///
+ /// Sets the value of the current plaintext to a given constant polynomial.
+ ///
+ ///
+ ///
+ /// Sets the value of the current plaintext to a given constant polynomial. The coefficient count
+ /// is set to one.
+ ///
+ /// The constant coefficient
+ public void Set(ulong constCoeff)
+ {
+ NativeMethods.Plaintext_Set(NativePtr, constCoeff);
+ }
+
+
+ ///
+ /// Sets a given range of coefficients of a plaintext polynomial to zero.
+ ///
+ ///
+ /// The index of the first coefficient to set to zero
+ /// The number of coefficients to set to zero
+ /// if startCoeff is not within [0, CoeffCount)
+ /// if startCoeff + length is not within [0, CoeffCount)
+ /// */
+ public void SetZero(ulong startCoeff, ulong length)
+ {
+ try
+ {
+ NativeMethods.Plaintext_SetZero(NativePtr, startCoeff, length);
+ }
+ catch(COMException e)
+ {
+ if ((uint)e.HResult == NativeMethods.Errors.HRInvalidIndex)
+ throw new ArgumentOutOfRangeException("startCoeff or length out of range", e);
+ throw;
+ }
+ }
+
+ ///
+ /// Sets the plaintext polynomial coefficients to zero starting at a given
+ /// index.
+ ///
+ /// The index of the first coefficient to set to zero
+ /// if startCoeff is not within [0, CoeffCount)
+ public void SetZero(ulong startCoeff)
+ {
+ try
+ {
+ NativeMethods.Plaintext_SetZero(NativePtr, startCoeff);
+ }
+ catch (COMException e)
+ {
+ if ((uint)e.HResult == NativeMethods.Errors.HRInvalidIndex)
+ throw new ArgumentOutOfRangeException("startCoeff or length out of range", e);
+ throw;
+ }
+ }
+
+ ///
+ /// Sets the plaintext polynomial to zero.
+ ///
+ public void SetZero()
+ {
+ NativeMethods.Plaintext_SetZero(NativePtr);
+ }
+
+ ///
+ /// Gets/set the value of a given coefficient of the plaintext polynomial.
+ ///
+ /// The index of the coefficient in the plaintext polynomial
+ /// if coeffIndex is not within [0, CoeffCount)
+ public ulong this[ulong coeffIndex]
+ {
+ get
+ {
+ NativeMethods.Plaintext_CoeffAt(NativePtr, coeffIndex, out ulong result);
+ return result;
+ }
+ set
+ {
+ NativeMethods.Plaintext_SetCoeffAt(NativePtr, coeffIndex, value);
+ }
+ }
+
+ ///
+ /// Returns whether the plaintext polynomial has all zero coefficients.
+ ///
+ public bool IsZero
+ {
+ get
+ {
+ NativeMethods.Plaintext_IsZero(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns the capacity of the current allocation.
+ ///
+ public ulong Capacity
+ {
+ get
+ {
+ NativeMethods.Plaintext_Capacity(NativePtr, out ulong capacity);
+ return capacity;
+ }
+ }
+
+ ///
+ /// Returns the coefficient count of the current plaintext polynomial.
+ ///
+ public ulong CoeffCount
+ {
+ get
+ {
+ NativeMethods.Plaintext_CoeffCount(NativePtr, out ulong result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns the significant coefficient count of the current plaintext polynomial.
+ ///
+ public ulong SignificantCoeffCount
+ {
+ get
+ {
+ NativeMethods.Plaintext_SignificantCoeffCount(NativePtr, out ulong result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns the non-zero coefficient count of the current plaintext polynomial.
+ ///
+ public ulong NonZeroCoeffCount
+ {
+ get
+ {
+ NativeMethods.Plaintext_NonZeroCoeffCount(NativePtr, out ulong result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns a human-readable string description of the plaintext polynomial.
+ ///
+ ///
+ ///
+ /// Returns a human-readable string description of the plaintext polynomial.
+ ///
+ ///
+ /// The returned string is of the form "7FFx^3 + 1x^1 + 3" with a format summarized by the following:
+ ///
+ /// - Terms are listed in order of strictly decreasing exponent
+ /// - Coefficient values are non-negative and in hexadecimal format (hexadecimal letters are in upper-case)
+ /// - Exponents are positive and in decimal format
+ /// - Zero coefficient terms (including the constant term) are omitted unless the polynomial is exactly 0 (see rule 9)
+ /// - Term with the exponent value of one is written as x^1
+ /// - Term with the exponent value of zero (the constant term) is written as just a hexadecimal number without x or exponent
+ /// - Terms are separated exactly by <space>+<space>
+ /// - Other than the +, no other terms have whitespace
+ /// - If the polynomial is exactly 0, the string "0" is returned
+ ///
+ ///
+ ///
+ /// if the plaintext is in NTT transformed form
+ public override string ToString()
+ {
+ NativeMethods.Plaintext_ToString(NativePtr, null, out ulong length);
+ StringBuilder buffer = new StringBuilder(checked((int)length));
+ NativeMethods.Plaintext_ToString(NativePtr, buffer, out length);
+ return buffer.ToString();
+ }
+
+ ///
+ /// Returns a hash-code based on the value of the plaintext polynomial.
+ ///
+ public override int GetHashCode()
+ {
+ ulong coeffCount = CoeffCount;
+ ulong[] coeffs = new ulong[coeffCount];
+
+ for (ulong i = 0; i < coeffCount; i++)
+ {
+ coeffs[i] = this[i];
+ }
+
+ return Utilities.ComputeArrayHashCode(coeffs);
+ }
+
+ ///
+ /// Returns an upper bound on the size of the ciphertext, as if it was written
+ /// to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.Plaintext_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the Plaintext to an output stream.
+ ///
+ /// Saves the Plaintext to an output stream. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the Plaintext to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.Plaintext_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ /// Loads a plaintext from an input stream overwriting the current
+ /// plaintext.
+ ///
+ /// Loads a plaintext from an input stream overwriting the current plaintext.
+ /// No checking of the validity of the plaintext data against encryption
+ /// parameters is performed. This function should not be used unless the
+ /// plaintext comes from a fully trusted source.
+ ///
+ /// The SEALContext
+ /// The stream to load the plaintext from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long UnsafeLoad(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.Plaintext_UnsafeLoad(context.NativePtr, NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ /// Loads a plaintext from an input stream overwriting the current
+ /// plaintext.
+ ///
+ /// Loads a plaintext from an input stream overwriting the current plaintext.
+ /// The loaded plaintext is verified to be valid for the given SEALContext.
+ ///
+ /// The SEALContext
+ /// The stream to load the plaintext from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long Load(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.Plaintext_Load(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ ///
+ /// Returns whether the plaintext is in NTT form.
+ ///
+ public bool IsNTTForm
+ {
+ get
+ {
+ NativeMethods.Plaintext_IsNTTForm(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns a copy of ParmsId. The ParmsId must remain zero unless the
+ /// plaintext polynomial is in NTT form.
+ ///
+ /// see EncryptionParameters for more
+ /// information about parmsId.
+ public ParmsId ParmsId
+ {
+ get
+ {
+ ParmsId parms = new ParmsId();
+ NativeMethods.Plaintext_GetParmsId(NativePtr, parms.Block);
+ return parms;
+ }
+
+ private set
+ {
+ NativeMethods.Plaintext_SetParmsId(NativePtr, value.Block);
+ }
+ }
+
+ ///
+ /// Returns a reference to the scale. This is only needed when using the
+ /// CKKS encryption scheme. The user should have little or no reason to ever
+ /// change the scale by hand.
+ ///
+ public double Scale
+ {
+ get
+ {
+ NativeMethods.Plaintext_Scale(NativePtr, out double scale);
+ return scale;
+ }
+
+ private set
+ {
+ NativeMethods.Plaintext_SetScale(NativePtr, value);
+ }
+ }
+
+ ///
+ /// Returns the currently used MemoryPoolHandle.
+ ///
+ public MemoryPoolHandle Pool
+ {
+ get
+ {
+ NativeMethods.Plaintext_Pool(NativePtr, out IntPtr pool);
+ MemoryPoolHandle handle = new MemoryPoolHandle(pool);
+ return handle;
+ }
+ }
+
+ ///
+ /// Returns whether or not the plaintext has the same semantic value as a given
+ /// plaintext.
+ ///
+ ///
+ /// Returns whether or not the plaintext has the same semantic value as a given
+ /// plaintext. Leading zero coefficients are ignored by the comparison.
+ ///
+ /// The object to compare against
+ public override bool Equals(object obj)
+ {
+ Plaintext pt = obj as Plaintext;
+ return Equals(pt);
+ }
+
+ ///
+ /// Returns whether or not the plaintext has the same semantic value as a given
+ /// plaintext.
+ ///
+ ///
+ /// Returns whether or not the plaintext has the same semantic value as a given
+ /// plaintext. Leading zero coefficients are ignored by the comparison.
+ ///
+ /// The plaintext to compare against
+ public bool Equals(Plaintext other)
+ {
+ if (null == other)
+ return false;
+
+ NativeMethods.Plaintext_Equals(NativePtr, other.NativePtr, out bool equals);
+ return equals;
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.Plaintext_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/PublicKey.cs b/bigpiseal3.5.1/dotnet/src/PublicKey.cs
new file mode 100644
index 0000000000000000000000000000000000000000..325c54937e43f6a7f351974f96192aa8a26aaa12
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/PublicKey.cs
@@ -0,0 +1,235 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Class to store a public key.
+ ///
+ ///
+ ///
+ /// Thread Safety
+ /// In general, reading from PublicKey is thread-safe as long as no other thread
+ /// is concurrently mutating it. This is due to the underlying data structure
+ /// storing the public key not being thread-safe.
+ ///
+ ///
+ public class PublicKey : NativeObject
+ {
+ ///
+ /// Creates an empty public key.
+ ///
+ public PublicKey()
+ {
+ NativeMethods.PublicKey_Create(out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a new PublicKey by copying an old one.
+ ///
+ /// The PublicKey to copy from
+ /// if copy is null
+ public PublicKey(PublicKey copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.PublicKey_Create(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a new PublicKey by initializing with a pointer to a native object.
+ ///
+ /// Pointer to native PublicKey
+ /// Whether this instance owns the native pointer
+ internal PublicKey(IntPtr publicKeyPtr, bool owned = true)
+ : base(publicKeyPtr, owned)
+ {
+ }
+
+ ///
+ /// Copies an old PublicKey to the current one.
+ ///
+ /// The PublicKey to copy from
+ /// if assign is null
+ public void Set(PublicKey assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.PublicKey_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Returns the underlying Ciphertext.
+ ///
+ ///
+ /// Returns the underlying Ciphertext. The returned Ciphertext is valid
+ /// only as long as the PublicKey is valid and not changed.
+ ///
+ public Ciphertext Data
+ {
+ get
+ {
+ NativeMethods.PublicKey_Data(NativePtr, out IntPtr cipherPtr);
+ Ciphertext cipher = new Ciphertext(cipherPtr, owned: false);
+ return cipher;
+ }
+ }
+
+ ///
+ /// Returns an upper bound on the size of the PublicKey, as if it was written
+ /// to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.PublicKey_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the PublicKey to an output stream.
+ ///
+ /// Saves the PublicKey to an output stream. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the PublicKey to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.PublicKey_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ /// Loads a PublicKey from an input stream overwriting the current
+ /// PublicKey.
+ ///
+ /// Loads a PublicKey from an input stream overwriting the current PublicKey.
+ /// No checking of the validity of the PublicKey data against encryption
+ /// parameters is performed. This function should not be used unless the
+ /// PublicKey comes from a fully trusted source.
+ ///
+ /// The SEALContext
+ /// The stream to load the PublicKey from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long UnsafeLoad(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.PublicKey_UnsafeLoad(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ /// Loads a PublicKey from an input stream overwriting the current
+ /// PublicKey.
+ ///
+ /// Loads a PublicKey from an input stream overwriting the current PublicKey.
+ /// The loaded PublicKey is verified to be valid for the given SEALContext.
+ ///
+ /// The SEALContext
+ /// The stream to load the PublicKey from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long Load(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.PublicKey_Load(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ ///
+ /// Returns a copy of ParmsId.
+ ///
+ public ParmsId ParmsId
+ {
+ get
+ {
+ ParmsId parmsId = new ParmsId();
+ NativeMethods.PublicKey_ParmsId(NativePtr, parmsId.Block);
+ return parmsId;
+ }
+ }
+
+ ///
+ /// Returns the currently used MemoryPoolHandle.
+ ///
+ public MemoryPoolHandle Pool
+ {
+ get
+ {
+ NativeMethods.PublicKey_Pool(NativePtr, out IntPtr pool);
+ MemoryPoolHandle handle = new MemoryPoolHandle(pool);
+ return handle;
+ }
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.PublicKey_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/RelinKeys.cs b/bigpiseal3.5.1/dotnet/src/RelinKeys.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d84dfc1c68b58e77885cf96f54f21f4ac439fc5c
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/RelinKeys.cs
@@ -0,0 +1,131 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Class to store relinearization keys.
+ ///
+ ///
+ ///
+ /// Relinearization
+ /// Freshly encrypted ciphertexts have a size of 2, and multiplying ciphertexts
+ /// of sizes K and L results in a ciphertext of size K+L-1. Unfortunately, this
+ /// growth in size slows down further multiplications and increases noise growth.
+ /// Relinearization is an operation that has no semantic meaning, but it reduces
+ /// the size of ciphertexts back to 2. Microsoft SEAL can only relinearize size 3
+ /// ciphertexts back to size 2, so if the ciphertexts grow larger than size 3,
+ /// there is no way to reduce their size. Relinearization requires an instance of
+ /// RelinKeys to be created by the secret key owner and to be shared with the
+ /// evaluator. Note that plain multiplication is fundamentally different from
+ /// normal multiplication and does not result in ciphertext size growth.
+ ///
+ ///
+ /// When to Relinearize
+ /// Typically, one should always relinearize after each multiplications. However,
+ /// in some cases relinearization should be postponed as late as possible due to
+ /// its computational cost.For example, suppose the computation involves several
+ /// homomorphic multiplications followed by a sum of the results. In this case it
+ /// makes sense to not relinearize each product, but instead add them first and
+ /// only then relinearize the sum. This is particularly important when using the
+ /// CKKS scheme, where relinearization is much more computationally costly than
+ /// multiplications and additions.
+ ///
+ ///
+ /// Thread Safety
+ /// In general, reading from RelinKeys is thread-safe as long as no other thread
+ /// is concurrently mutating it. This is due to the underlying data structure
+ /// storing the relinearization keys not being thread-safe.
+ ///
+ ///
+ public class RelinKeys :
+ KSwitchKeys,
+ ISerializableObject,
+ ISettable
+ {
+ ///
+ /// Creates an empty set of relinearization keys.
+ ///
+ public RelinKeys() : base()
+ {
+ }
+
+ ///
+ /// Creates a new RelinKeys instance by copying a given instance.
+ ///
+ /// The RelinKeys to copy from
+ /// if copy is null
+ public RelinKeys(RelinKeys copy)
+ : base(copy)
+ {
+ }
+
+ ///
+ /// Creates a new RelinKeys instance initialized with a pointer to a native
+ /// KSwitchKeys object.
+ ///
+ /// Pointer to native KSwitchKeys object
+ /// Whether this instance owns the native pointer
+ internal RelinKeys(IntPtr kswitchKeys, bool owned = true)
+ : base(kswitchKeys, owned)
+ {
+ }
+
+ ///
+ /// Copies a given RelinKeys instance to the current one.
+ ///
+ ///
+ /// The RelinKeys to copy from
+ /// if assign is null
+ public void Set(RelinKeys assign)
+ {
+ base.Set(assign);
+ }
+
+ ///
+ /// Returns the index of a relinearization key in the backing KSwitchKeys
+ /// instance that corresponds to the given secret key power, assuming that
+ /// it exists in the backing KSwitchKeys.
+ ///
+ /// The power of the secret key
+ /// if keyPower is less than 2
+ public static ulong GetIndex(ulong keyPower)
+ {
+ NativeMethods.RelinKeys_GetIndex(keyPower, out ulong index);
+ return index;
+ }
+
+ ///
+ /// Returns whether a relinearization key corresponding to a given secret
+ /// key power exists.
+ ///
+ /// The power of the secret key
+ /// if keyPower is less than 2
+ public bool HasKey(ulong keyPower)
+ {
+ ulong index = GetIndex(keyPower);
+ return (ulong)Data.LongCount() > index &&
+ Data.ElementAt(checked((int)index)).Count() != 0;
+ }
+
+ ///
+ /// Returns a specified relinearization key.
+ ///
+ ///
+ /// Returns a specified relinearization key. The returned relinearization
+ /// key corresponds to the given power of the secret key and is valid only
+ /// as long as the RelinKeys is valid.
+ ///
+ /// The power of the secret key
+ /// if the key corresponding to keyPower
+ /// does not exist
+ public IEnumerable Key(ulong keyPower)
+ {
+ return Data.ElementAt(checked((int)GetIndex(keyPower)));
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/SEALContext.cs b/bigpiseal3.5.1/dotnet/src/SEALContext.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e7a3d843417097c60ffd66f30e869f9d914786e0
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/SEALContext.cs
@@ -0,0 +1,521 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.Text;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Performs sanity checks (validation) and pre-computations for a given set of encryption
+ /// parameters.
+ ///
+ ///
+ ///
+ ///
+ /// Performs sanity checks (validation) and pre-computations for a given set of encryption
+ /// parameters. While the EncryptionParameters class is intended to be a light-weight class
+ /// to store the encryption parameters, the SEALContext class is a heavy-weight class that
+ /// is constructed from a given set of encryption parameters. It validates the parameters
+ /// for correctness, evaluates their properties, and performs and stores the results of
+ /// several costly pre-computations.
+ ///
+ ///
+ /// After the user has set at least the PolyModulus, CoeffModulus, and PlainModulus
+ /// parameters in a given EncryptionParameters instance, the parameters can be validated
+ /// for correctness and functionality by constructing an instance of SEALContext. The
+ /// constructor of SEALContext does all of its work automatically, and concludes by
+ /// constructing and storing an instance of the EncryptionParameterQualifiers class, with
+ /// its flags set according to the properties of the given parameters. If the created
+ /// instance of EncryptionParameterQualifiers has the ParametersSet flag set to true, the
+ /// given parameter set has been deemed valid and is ready to be used. If the parameters
+ /// were for some reason not appropriately set, the ParametersSet flag will be false,
+ /// and a new SEALContext will have to be created after the parameters are corrected.
+ ///
+ ///
+ /// By default, SEALContext creates a chain of SEALContext.ContextData instances. The
+ /// first one in the chain corresponds to special encryption parameters that are reserved
+ /// to be used by the various key classes (SecretKey, PublicKey, etc.). These are the
+ /// exact same encryption parameters that are created by the user and passed to the
+ /// constructor of SEALContext. The properties KeyContextData and KeyParmsId return the
+ /// ContextData and the ParmsId corresponding to these special parameters. The rest of the
+ /// ContextData instances in the chain correspond to encryption parameters that are derived
+ /// from the first encryption parameters by always removing the last one of the moduli in
+ /// the CoeffModulus, until the resulting parameters are no longer valid, e.g., there are
+ /// no more primes left. These derived encryption parameters are used by ciphertexts and
+ /// plaintexts and their respective ContextData can be accessed through the
+ /// GetContextData(ParmsId) function. The properties FirstContextData and LastContextData
+ /// return the ContextData corresponding to the first and the last set of parameters in
+ /// the "data" part of the chain, i.e., the second and the last element in the full chain.
+ /// The chain is a doubly linked list and is referred to as the modulus switching chain.
+ ///
+ ///
+ /// see EncryptionParameters for more details on the parameters.
+ /// see EncryptionParameterQualifiers for more details on the qualifiers.
+ public class SEALContext : NativeObject
+ {
+ ///
+ /// Creates an instance of SEALContext and performs several pre-computations
+ /// on the given EncryptionParameters.
+ ///
+ /// The encryption parameters.
+ /// Determines whether the modulus switching chain
+ /// should be created
+ /// Determines whether a specific security level should be
+ /// enforced according to HomomorphicEncryption.org security standard
+ /// if parms is null
+ public SEALContext(EncryptionParameters parms,
+ bool expandModChain = true, SecLevelType secLevel = SecLevelType.TC128)
+ {
+ if (null == parms)
+ throw new ArgumentNullException(nameof(parms));
+
+ NativeMethods.SEALContext_Create(parms.NativePtr,
+ expandModChain, (int)secLevel, out IntPtr context);
+ NativePtr = context;
+ }
+
+ ///
+ /// Returns the ContextData corresponding to encryption parameters with a given
+ /// parmsId. If parameters with the given ParmsId are not found then the function
+ /// returns null.
+ ///
+ ///
+ /// The ParmsId of the encryption parameters
+ /// if parmsId is null
+ public ContextData GetContextData(ParmsId parmsId)
+ {
+ if (null == parmsId)
+ throw new ArgumentNullException(nameof(parmsId));
+
+ NativeMethods.SEALContext_GetContextData(NativePtr, parmsId.Block, out IntPtr contextData);
+ if (IntPtr.Zero.Equals(contextData))
+ return null;
+
+ ContextData data = new ContextData(contextData, owned: false);
+ return data;
+ }
+
+ ///
+ /// Returns the ContextData corresponding to encryption parameters that are
+ /// used for keys.
+ ///
+ public ContextData KeyContextData
+ {
+ get
+ {
+ NativeMethods.SEALContext_KeyContextData(NativePtr, out IntPtr contextData);
+ ContextData data = new ContextData(contextData, owned: false);
+ return data;
+ }
+ }
+
+ ///
+ /// Returns the ContextData corresponding to the first encryption parameters
+ /// that are used for data.
+ ///
+ public ContextData FirstContextData
+ {
+ get
+ {
+ NativeMethods.SEALContext_FirstContextData(NativePtr, out IntPtr contextData);
+ ContextData data = new ContextData(contextData, owned: false);
+ return data;
+ }
+ }
+
+ ///
+ /// Returns the ContextData corresponding to the last encryption parameters
+ /// that are used for data.
+ ///
+ public ContextData LastContextData
+ {
+ get
+ {
+ NativeMethods.SEALContext_LastContextData(NativePtr, out IntPtr contextData);
+ ContextData data = new ContextData(contextData, owned: false);
+ return data;
+ }
+ }
+
+ ///
+ /// Returns whether the encryption parameters are valid.
+ ///
+ public bool ParametersSet
+ {
+ get
+ {
+ NativeMethods.SEALContext_ParametersSet(NativePtr, out bool paramsSet);
+ return paramsSet;
+ }
+ }
+
+ ///
+ /// If the encryption parameters are set in a way that is considered valid by SEAL, return "success".
+ /// If the encryption parameters are set but not validated yet, return "none".
+ /// Otherwise, return a brief reason.
+ ///
+ public string ParameterErrorName()
+ {
+ NativeMethods.SEALContext_ParameterErrorName(NativePtr, null, out ulong length);
+ byte[] buffer = new byte[length];
+ NativeMethods.SEALContext_ParameterErrorName(NativePtr, buffer, out length);
+ return Encoding.ASCII.GetString(buffer);
+ }
+
+ ///
+ /// If the encryption parameters are set in a way that is considered valid by SEAL, return "valid".
+ /// Otherwise, return a comprehensive reason.
+ ///
+ public string ParameterErrorMessage()
+ {
+ NativeMethods.SEALContext_ParameterErrorMessage(NativePtr, null, out ulong length);
+ byte[] buffer = new byte[length];
+ NativeMethods.SEALContext_ParameterErrorMessage(NativePtr, buffer, out length);
+ return Encoding.ASCII.GetString(buffer);
+ }
+
+ ///
+ /// Returns a ParmsId corresponding to the set of encryption parameters
+ /// that are used for keys.
+ ///
+ public ParmsId KeyParmsId
+ {
+ get
+ {
+ ParmsId parms = new ParmsId();
+ NativeMethods.SEALContext_KeyParmsId(NativePtr, parms.Block);
+ return parms;
+ }
+ }
+
+ ///
+ /// Returns a ParmsId corresponding to the first encryption parameters that
+ /// are used for data.
+ ///
+ public ParmsId FirstParmsId
+ {
+ get
+ {
+ ParmsId parms = new ParmsId();
+ NativeMethods.SEALContext_FirstParmsId(NativePtr, parms.Block);
+ return parms;
+ }
+ }
+
+ ///
+ /// Returns a ParmsId corresponding to the last encryption parameters that
+ /// are used for data.
+ ///
+ public ParmsId LastParmsId
+ {
+ get
+ {
+ ParmsId parms = new ParmsId();
+ NativeMethods.SEALContext_LastParmsId(NativePtr, parms.Block);
+ return parms;
+ }
+ }
+
+
+ ///
+ /// Returns whether the coefficient modulus supports keyswitching.
+ ///
+ ///
+ /// Returns whether the coefficient modulus supports keyswitching. In
+ /// practice, support for keyswitching is required by Evaluator.Relinearize,
+ /// Evaluator.ApplyGalois, and all rotation and conjugation operations.
+ /// For keyswitching to be available, the coefficient modulus parameter must
+ /// consist of at least two prime number factors.
+ ///
+ public bool UsingKeyswitching
+ {
+ get
+ {
+ NativeMethods.SEALContext_UsingKeyswitching(NativePtr, out bool result);
+ return result;
+ }
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.SEALContext_Destroy(NativePtr);
+ }
+
+ ///
+ /// Class to hold pre-computation data for a given set of encryption parameters.
+ ///
+ public class ContextData : NativeObject
+ {
+ ///
+ /// Build a ContextData object from a native pointer.
+ ///
+ /// Pointer to native object
+ /// Whether this instance owns the native object
+ internal ContextData(IntPtr ptr, bool owned = true)
+ : base(ptr, owned)
+ {
+ }
+
+ ///
+ /// Returns a copy of the underlying encryption parameters.
+ ///
+ public EncryptionParameters Parms
+ {
+ get
+ {
+ NativeMethods.ContextData_Parms(NativePtr, out IntPtr parms);
+ return new EncryptionParameters(parms);
+ }
+ }
+
+ ///
+ /// Returns the ParmsId of the current parameters.
+ ///
+ public ParmsId ParmsId
+ {
+ get
+ {
+ return Parms.ParmsId;
+ }
+ }
+
+
+ ///
+ /// Returns a copy of EncryptionParameterQualifiers corresponding to the
+ /// current encryption parameters.
+ ///
+ ///
+ /// Returns a copy of EncryptionParameterQualifiers corresponding to the
+ /// current encryption parameters. Note that to change the qualifiers it is
+ /// necessary to create a new instance of SEALContext once appropriate changes
+ /// to the encryption parameters have been made.
+ ///
+ public EncryptionParameterQualifiers Qualifiers
+ {
+ get
+ {
+ NativeMethods.ContextData_Qualifiers(NativePtr, out IntPtr epq);
+ EncryptionParameterQualifiers qualifiers = new EncryptionParameterQualifiers(epq);
+ return qualifiers;
+ }
+ }
+
+ ///
+ /// Returns a the pre-computed product of all primes in the
+ /// coefficient modulus.
+ ///
+ ///
+ /// Returns a the pre-computed product of all primes in the
+ /// coefficient modulus. The security of the encryption parameters largely depends
+ /// on the bit-length of this product, and on the degree of the polynomial modulus.
+ ///
+ public ulong[] TotalCoeffModulus
+ {
+ get
+ {
+ ulong count = 0;
+ NativeMethods.ContextData_TotalCoeffModulus(NativePtr, ref count, null);
+
+ ulong[] result = new ulong[count];
+ NativeMethods.ContextData_TotalCoeffModulus(NativePtr, ref count, result);
+
+ return result;
+ }
+ }
+
+ ///
+ /// Returns the significant bit count of the total coefficient modulus.
+ ///
+ public int TotalCoeffModulusBitCount
+ {
+ get
+ {
+ NativeMethods.ContextData_TotalCoeffModulusBitCount(NativePtr, out int bitCount);
+ return bitCount;
+ }
+ }
+
+ ///
+ /// Return a copy of BFV "Delta", i.e. coefficient modulus divided by
+ /// plaintext modulus.
+ ///
+ public ulong[] CoeffDivPlainModulus
+ {
+ get
+ {
+ ulong count = 0;
+ NativeMethods.ContextData_CoeffDivPlainModulus(NativePtr, ref count, null);
+
+ ulong[] cdpm = new ulong[count];
+ NativeMethods.ContextData_CoeffDivPlainModulus(NativePtr, ref count, cdpm);
+
+ return cdpm;
+ }
+ }
+
+ ///
+ /// Return the threshold for the upper half of integers modulo PlainModulus.
+ /// This is simply(PlainModulus + 1) / 2.
+ ///
+ public ulong PlainUpperHalfThreshold
+ {
+ get
+ {
+ NativeMethods.ContextData_PlainUpperHalfThreshold(NativePtr, out ulong puht);
+ return puht;
+ }
+ }
+
+ ///
+ /// Return a copy of the plaintext upper half increment, i.e. coeffModulus
+ /// minus plainModulus.
+ ///
+ ///
+ /// Return a copy of the plaintext upper half increment, i.e. coeffModulus
+ /// minus plainModulus. The upper half increment is represented as an integer
+ /// for the full product coeffModulus if UsingFastPlainLift is false and is
+ /// otherwise represented modulo each of the CoeffModulus primes in order.
+ ///
+ public ulong[] PlainUpperHalfIncrement
+ {
+ get
+ {
+ ulong count = 0;
+ NativeMethods.ContextData_PlainUpperHalfIncrement(NativePtr, ref count, null);
+
+ ulong[] puhi = new ulong[count];
+ NativeMethods.ContextData_PlainUpperHalfIncrement(NativePtr, ref count, puhi);
+
+ return puhi;
+ }
+ }
+
+ ///
+ /// Return a copy of the upper half threshold with respect to the total
+ /// coefficient modulus. This is needed in CKKS decryption.
+ ///
+ public ulong[] UpperHalfThreshold
+ {
+ get
+ {
+ ulong count = 0;
+ NativeMethods.ContextData_UpperHalfThreshold(NativePtr, ref count, null);
+
+ if (count == 0)
+ return null;
+
+ ulong[] uht = new ulong[count];
+ NativeMethods.ContextData_UpperHalfThreshold(NativePtr, ref count, uht);
+
+ return uht;
+ }
+ }
+
+ ///
+ /// Return a copy of the upper half increment used for computing Delta*m
+ /// and converting the coefficients to modulo CoeffModulus.
+ ///
+ ///
+ /// Return a copy of the upper half increment used for computing Delta*m
+ /// and converting the coefficients to modulo CoeffModulus. For example,
+ /// t-1 in plaintext should change into
+ /// q - Delta = Delta*t + r_t(q) - Delta = Delta*(t-1) + r_t(q)
+ /// so multiplying the message by Delta is not enough and requires also an
+ /// addition of r_t(q). This is precisely the UpperHalfIncrement. Note that
+ /// this operation is only done for negative message coefficients, i.e. those
+ /// that exceed PlainUpperHalfThreshold.
+ ///
+ public ulong[] UpperHalfIncrement
+ {
+ get
+ {
+ ulong count = 0;
+ NativeMethods.ContextData_UpperHalfIncrement(NativePtr, ref count, null);
+
+ if (count == 0)
+ return null;
+
+ ulong[] uhi = new ulong[count];
+ NativeMethods.ContextData_UpperHalfIncrement(NativePtr, ref count, uhi);
+
+ return uhi;
+ }
+ }
+
+ ///
+ /// Returns the context data corresponding to the previous parameters in the
+ /// modulus switching chain.
+ ///
+ ///
+ /// Returns the context data corresponding to the previous parameters in the
+ /// modulus switching chain. If the current data is the first one in the chain,
+ /// then the result is nullptr.
+ ///
+ public ContextData PrevContextData
+ {
+ get
+ {
+ NativeMethods.ContextData_PrevContextData(NativePtr, out IntPtr prev);
+
+ if (IntPtr.Zero.Equals(prev))
+ return null;
+
+ ContextData data = new ContextData(prev, owned: false);
+ return data;
+ }
+ }
+
+ ///
+ /// Returns the context data corresponding to the next parameters in the modulus
+ /// switching chain.
+ ///
+ ///
+ /// Returns the context data corresponding to the next parameters in the modulus
+ /// switching chain. If the current data is the last one in the chain, then the
+ /// result is nullptr.
+ ///
+ public ContextData NextContextData
+ {
+ get
+ {
+ NativeMethods.ContextData_NextContextData(NativePtr, out IntPtr next);
+
+ if (IntPtr.Zero.Equals(next))
+ return null;
+
+ ContextData data = new ContextData(next, owned: false);
+ return data;
+ }
+ }
+
+ ///
+ /// Returns the index of the parameter set in a chain.
+ ///
+ ///
+ /// Returns the index of the parameter set in a chain. The initial parameters
+ /// have index 0 and the index increases sequentially in the parameter chain.
+ ///
+ public ulong ChainIndex
+ {
+ get
+ {
+ NativeMethods.ContextData_ChainIndex(NativePtr, out ulong index);
+ return index;
+ }
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.ContextData_Destroy(NativePtr);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/bigpiseal3.5.1/dotnet/src/SEALNet.csproj b/bigpiseal3.5.1/dotnet/src/SEALNet.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..d7503c5be743392ce968516aebb74d0d4154b0e6
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/SEALNet.csproj
@@ -0,0 +1,26 @@
+
+
+ netstandard2.0
+ false
+ Microsoft Research
+ Microsoft Corporation
+ .NET wrapper library for Microsoft SEAL
+ Microsoft Corporation 2020
+ true
+ SEALNetCert.snk
+ true
+
+
+ $(ProjectDir)../../lib/dotnet/$(Configuration)/SEALNet.xml
+ x64
+ $(ProjectDir)../../lib/dotnet/$(Configuration)
+
+
+
+ pdbonly
+ true
+
+
+ DEBUG;TRACE
+
+
diff --git a/bigpiseal3.5.1/dotnet/src/SecretKey.cs b/bigpiseal3.5.1/dotnet/src/SecretKey.cs
new file mode 100644
index 0000000000000000000000000000000000000000..59ad22b94776bc168d38fa95bcf3a0c70387324d
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/SecretKey.cs
@@ -0,0 +1,239 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Class to store a secret key.
+ ///
+ ///
+ ///
+ /// Thread Safety
+ /// In general, reading from SecretKey is thread-safe as long as no other
+ /// thread is concurrently mutating it. This is due to the underlying data
+ /// structure storing the secret key not being thread-safe.
+ ///
+ ///
+ /// see KeyGenerator for the class that generates the secret key.
+ /// see PublicKey for the class that stores the public key.
+ /// see RelinKeys for the class that stores the relinearization keys.
+ /// see GaloisKeys for the class that stores the Galois keys.
+ public class SecretKey : NativeObject
+ {
+ ///
+ /// Creates an empty secret key.
+ ///
+ public SecretKey()
+ {
+ NativeMethods.SecretKey_Create(out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Creates a new SecretKey by initializing it with a pointer to a native object.
+ ///
+ /// The native SecretKey pointer
+ /// Whether this instance owns the native pointer
+ internal SecretKey(IntPtr secretKeyPtr, bool owned = true)
+ : base(secretKeyPtr, owned)
+ {
+ }
+
+ ///
+ /// Creates a new SecretKey by copying an old one.
+ ///
+ /// The SecretKey to copy from
+ /// if copy is null
+ public SecretKey(SecretKey copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ NativeMethods.SecretKey_Create(copy.NativePtr, out IntPtr ptr);
+ NativePtr = ptr;
+ }
+
+ ///
+ /// Copies an old SecretKey to the current one.
+ ///
+ /// The SecretKey to copy from
+ /// if assign is null
+ public void Set(SecretKey assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ NativeMethods.SecretKey_Set(NativePtr, assign.NativePtr);
+ }
+
+ ///
+ /// Returns the underlying Plaintext.
+ ///
+ ///
+ /// Returns the underlying Plaintext. The returned Plaintext is valid
+ /// only as long as the SecretKey is valid and not changed.
+ ///
+ public Plaintext Data
+ {
+ get
+ {
+ NativeMethods.SecretKey_Data(NativePtr, out IntPtr plaintextPtr);
+ Plaintext plaintext = new Plaintext(plaintextPtr, owned: false);
+ return plaintext;
+ }
+ }
+
+ ///
+ /// Returns an upper bound on the size of the SecretKey, as if it was written
+ /// to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ NativeMethods.SecretKey_SaveSize(
+ NativePtr, (byte)comprModeValue, out long outBytes);
+ return outBytes;
+ }
+
+ /// Saves the SecretKey to an output stream.
+ ///
+ /// Saves the SecretKey to an output stream. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the SecretKey to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ {
+ comprMode = comprMode ?? Serialization.ComprModeDefault;
+ if (!Serialization.IsSupportedComprMode(comprMode.Value))
+ throw new ArgumentException("Unsupported compression mode");
+
+ ComprModeType comprModeValue = comprMode.Value;
+ return Serialization.Save(
+ (byte[] outptr, ulong size, byte cm, out long outBytes) =>
+ NativeMethods.SecretKey_Save(NativePtr, outptr, size,
+ cm, out outBytes),
+ SaveSize(comprModeValue), comprModeValue, stream);
+ }
+
+ /// Loads a SecretKey from an input stream overwriting the current
+ /// SecretKey.
+ ///
+ /// Loads a SecretKey from an input stream overwriting the current SecretKey.
+ /// No checking of the validity of the SecretKey data against encryption
+ /// parameters is performed. This function should not be used unless the
+ /// SecretKey comes from a fully trusted source.
+ ///
+ /// The SEALContext
+ /// The stream to load the SecretKey from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long UnsafeLoad(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.SecretKey_UnsafeLoad(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ /// Loads a SecretKey from an input stream overwriting the current
+ /// SecretKey.
+ ///
+ /// Loads a SecretKey from an input stream overwriting the current SecretKey.
+ /// The loaded SecretKey is verified to be valid for the given SEALContext.
+ ///
+ /// The SEALContext
+ /// The stream to load the SecretKey from
+ /// if context or stream is
+ /// null
+ /// if the stream is closed or does not
+ /// support reading
+ /// if context is not set or encryption
+ /// parameters are not valid
+ /// if the stream ended
+ /// unexpectedly
+ /// if I/O operations failed
+ /// if the data cannot be loaded
+ /// by this version of Microsoft SEAL, if the loaded data is invalid, or if the
+ /// loaded compression mode is not supported
+ public long Load(SEALContext context, Stream stream)
+ {
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ return Serialization.Load(
+ (byte[] outptr, ulong size, out long outBytes) =>
+ NativeMethods.SecretKey_Load(NativePtr, context.NativePtr,
+ outptr, size, out outBytes),
+ stream);
+ }
+
+ ///
+ /// Returns a copy of ParmsId.
+ ///
+ public ParmsId ParmsId
+ {
+ get
+ {
+ ParmsId parms = new ParmsId();
+ NativeMethods.SecretKey_ParmsId(NativePtr, parms.Block);
+ return parms;
+ }
+ }
+
+ ///
+ /// Returns the currently used MemoryPoolHandle.
+ ///
+ public MemoryPoolHandle Pool
+ {
+ get
+ {
+ NativeMethods.SecretKey_Pool(NativePtr, out IntPtr pool);
+ MemoryPoolHandle handle = new MemoryPoolHandle(pool);
+ return handle;
+ }
+ }
+
+ ///
+ /// Destroy native object.
+ ///
+ protected override void DestroyNativeObject()
+ {
+ NativeMethods.SecretKey_Destroy(NativePtr);
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/Serializable.cs b/bigpiseal3.5.1/dotnet/src/Serializable.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d118d4acf5b4e2fe78181e9c071af6c3d4011ad5
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Serializable.cs
@@ -0,0 +1,186 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL.Tools;
+using System;
+using System.IO;
+
+namespace Microsoft.Research.SEAL
+{
+ /// Interface for classes with a Set function.
+ public interface ISettable where T : class
+ {
+ ///
+ /// Copies a given object to the current one.
+ ///
+ /// The object to copy from
+ /// if assign is null
+ void Set(T assign);
+ }
+
+ /// Interface for classes that are serializable.
+ public interface ISerializableObject
+ {
+ ///
+ /// Returns an upper bound on the size of the object, as if it was written
+ /// to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ long SaveSize(ComprModeType? comprMode);
+
+ /// Saves the object to an output stream.
+ ///
+ /// Saves the object to an output stream. The output is in binary format
+ /// and not human-readable.
+ ///
+ /// The stream to save the object to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ long Save(Stream stream, ComprModeType? comprMode);
+ }
+
+ /// Class to represent a serializable object.
+ ///
+ ///
+ /// Some functions return serializable objects rather than normal objects. For
+ /// example, Encryptor can be used in symmetric-key mode to create symmetric-key
+ /// ciphertexts, where half of the ciphertext data is pseudo-random and can be
+ /// generated from a seed, reducing the size of the newly created ciphertext
+ /// object by nearly 50%. However, the compression only has an effect when the
+ /// object is serialized with compression mode ComprModeType.Deflate due to an
+ /// implementation detail. This makes sense when, e.g., the ciphertexts need
+ /// to be communicated from a client to a server for encrypted computation.
+ ///
+ ///
+ /// Serializable objects are created only by the following functions:
+ /// - Encryptor.EncryptSymmetric
+ /// - Encryptor.EncryptZeroSymmetric
+ /// - KeyGenerator.RelinKeys
+ /// - KeyGenerator.GaloisKeys
+ ///
+ ///
+ /// Serializable objects also expose the SaveSize function that behaves just
+ /// as the SaveSize functions of other objects in Microsoft SEAL: it returns
+ /// an upper bound on the size of a buffer needed to hold the serialized data.
+ ///
+ ///
+ /// The following illustrates the use of serializable objects:
+ ///
+ /// +--------------------------+
+ /// | Serializable{GaloisKeys} | Size 2 MB (example)
+ /// +------------+-------------+
+ /// |
+ /// | Serializable{GaloisKeys}.Save
+ /// | with ComprModeType.Deflate
+ /// |
+ /// +-------v-------+
+ /// | Stream/Buffer | Size ~1 MB (example)
+ /// +-------+-------+
+ /// |
+ /// |
+ /// +--v--+
+ /// Network Minimized communication
+ /// +--+--+
+ /// |
+ /// | GaloisKeys.Load
+ /// |
+ /// +-----v------+
+ /// | GaloisKeys | Size 2 MB (example)
+ /// +------------+
+ ///
+ /// The type to wrap into a serializable object
+ ///
+ public class Serializable : DisposableObject
+ where T : DisposableObject, ISerializableObject, ISettable, new()
+ {
+ ///
+ /// Constructs a new serializable object by copying a given one.
+ ///
+ /// The serializable object to copy from
+ /// if copy is null
+ public Serializable(Serializable copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ // Use Activator to get around lack of constructor
+ obj_ = (T)Activator.CreateInstance(typeof(T), copy.obj_);
+ }
+
+ ///
+ /// Copies a given serializable object to the current one.
+ ///
+ /// The serializable object to copy from
+ /// if assign is null
+ public void Set(Serializable assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ obj_.Set(assign.obj_);
+ }
+
+ ///
+ /// Returns an upper bound on the size of the serializable object, as if it
+ /// was written to an output stream.
+ ///
+ /// The compression mode
+ /// if the compression mode is not
+ /// supported
+ /// if the size does not fit in
+ /// the return type
+ public long SaveSize(ComprModeType? comprMode = null)
+ => obj_.SaveSize(comprMode);
+
+ /// Saves the serializable object to an output stream.
+ ///
+ /// Saves the serializable object to an output stream. The output is in
+ /// binary format and not human-readable.
+ ///
+ /// The stream to save the serializable object to
+ /// The desired compression mode
+ /// if stream is null
+ /// if the stream is closed or does not
+ /// support writing, or if compression mode is not supported
+ /// if I/O operations failed
+ /// if the data to be saved
+ /// is invalid, or if compression failed
+ public long Save(Stream stream, ComprModeType? comprMode = null)
+ => obj_.Save(stream, comprMode);
+
+ ///
+ /// Constructs a new serializable object wrapping a given object.
+ ///
+ /// The object to wrap
+ /// if obj is null
+ internal Serializable(T obj)
+ {
+ if (null == obj)
+ throw new ArgumentNullException(nameof(obj));
+
+ obj_ = obj;
+ }
+
+ ///
+ /// Destroy wrapped object.
+ ///
+ protected override void DisposeManagedResources()
+ {
+ obj_.Dispose();
+ }
+
+ ///
+ /// The object wrapped by an instance of Serializable.
+ ///
+ private readonly T obj_;
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/Serialization.cs b/bigpiseal3.5.1/dotnet/src/Serialization.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5865b2cfb0648f94e1433d661a2cc92684eeff5d
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Serialization.cs
@@ -0,0 +1,427 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// A type to describe the compression algorithm applied to serialized data.
+ /// Ciphertext and key data consist of a large number of 64-bit words storing
+ /// integers modulo prime numbers much smaller than the word size, resulting in
+ /// a large number of zero bytes in the output. Any compression algorithm should
+ /// be able to clean up these zero bytes and hence compress both ciphertext and
+ /// key data.
+ ///
+ public enum ComprModeType : byte
+ {
+ /// No compression is used.
+ None = 0,
+
+ /// Use Deflate compression.
+ Deflate = 1,
+ }
+
+ /// Class to provide functionality for serialization.
+ ///
+ /// Class to provide functionality for serialization. Most users of the library
+ /// should never have to call these functions explicitly, as they are called
+ /// internally by functions such as Ciphertext.Save and Ciphertext.Load.
+ ///
+ public abstract class Serialization
+ {
+ ///
+ /// The compression mode used by default.
+ ///
+ public static readonly ComprModeType ComprModeDefault = ((Func)(() => {
+ NativeMethods.Serialization_ComprModeDefault(out byte comprMode);
+ return (ComprModeType)comprMode;
+ }))();
+
+ /// The magic value indicating a Microsoft SEAL header.
+ public static readonly ushort SEALMagic = ((Func)(() => {
+ NativeMethods.Serialization_SEALMagic(out ushort sealMagic);
+ return sealMagic;
+ }))();
+
+ /// The size in bytes of the SEALHeader.
+ public static readonly byte SEALHeaderSize = ((Func)(() => {
+ NativeMethods.Serialization_SEALHeaderSize(out byte sealHeaderSize);
+ return sealHeaderSize;
+ }))();
+
+ /// Struct to contain header information for serialization.
+ ///
+ /// Struct to contain header information for serialization. The size of the header is 16 bytes and it consists
+ /// of the following fields:
+ ///
+ /// 1. a magic number identifying this is a SEALHeader struct (2 bytes)
+ /// 2. size in bytes of the SEALHeader struct (1 byte)
+ /// 3. Microsoft SEAL's major version number (1 byte)
+ /// 4. Microsoft SEAL's minor version number (1 byte)
+ /// 5. a ComprModeType indicating whether data after the header is compressed (1 byte)
+ /// 6. reserved for future use and data alignment (2 bytes)
+ /// 7. the size in bytes of the entire serialized object, including the header (8 bytes)
+ ///
+ [StructLayout(LayoutKind.Explicit, Size=16)]
+ public class SEALHeader : ISettable
+ {
+ /// A magic number identifying this is a SEALHeader struct (2 bytes)
+ [FieldOffset(0)]public ushort Magic = SEALMagic;
+
+ /// Size in bytes of the SEALHeader struct (1 byte)
+ [FieldOffset(2)]public byte HeaderSize = SEALHeaderSize;
+
+ /// Microsoft SEAL's major version number (1 byte)
+ [FieldOffset(3)]public byte VersionMajor = SEALVersion.Major;
+
+ /// Microsoft SEAL's minor version number (1 byte)
+ [FieldOffset(4)]public byte VersionMinor = SEALVersion.Minor;
+
+ /// A compr_mode_type indicating whether data after the header is compressed (1 byte)
+ [FieldOffset(5)]public ComprModeType ComprMode = ComprModeDefault;
+
+ /// Reserved for future use and data alignment (2 bytes)
+ [FieldOffset(6)]public ushort Reserved = 0;
+
+ /// The size in bytes of the entire serialized object, including the header (8 bytes)
+ [FieldOffset(8)]public ulong Size = 0;
+
+ ///
+ /// Copies a given SEALHeader to the current one.
+ ///
+ /// The SEALHeader to copy from
+ /// if assign is null
+ public void Set(SEALHeader assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ Magic = assign.Magic;
+ HeaderSize = assign.HeaderSize;
+ VersionMajor = assign.VersionMajor;
+ VersionMinor = assign.VersionMinor;
+ ComprMode = assign.ComprMode;
+ Reserved = assign.Reserved;
+ Size = assign.Size;
+ }
+ };
+
+ private static bool IsSupportedComprMode(byte comprMode)
+ {
+ NativeMethods.Serialization_IsSupportedComprMode(comprMode, out bool result);
+ return result;
+ }
+
+ /// Returns true if the given value corresponds to a supported compression mode.
+ /// The compression mode to validate
+ public static bool IsSupportedComprMode(ComprModeType comprMode) =>
+ IsSupportedComprMode((byte)comprMode);
+
+ /// Returns true if the SEALHeader has a version number compatible with this version of
+ /// Microsoft SEAL.
+ /// The SEALHeader
+ public static bool IsCompatibleVersion(SEALHeader header)
+ {
+ byte[] headerArray = new byte[SEALHeaderSize];
+ using (MemoryStream stream = new MemoryStream(headerArray))
+ {
+ SaveHeader(header, stream);
+ NativeMethods.Serialization_IsCompatibleVersion(
+ headerArray, (ulong)headerArray.Length, out bool result);
+ return result;
+ }
+ }
+
+ /// Returns true if the given SEALHeader is valid for this version of Microsoft SEAL.
+ /// The SEALHeader
+ public static bool IsValidHeader(SEALHeader header)
+ {
+ byte[] headerArray = new byte[SEALHeaderSize];
+ using (MemoryStream stream = new MemoryStream(headerArray))
+ {
+ SaveHeader(header, stream);
+ NativeMethods.Serialization_IsValidHeader(
+ headerArray, (ulong)headerArray.Length, out bool result);
+ return result;
+ }
+ }
+
+ /// Saves a SEALHeader to a given binary stream.
+ ///
+ /// Saves a SEALHeader to a given stream. The output is in binary format and not human-readable.
+ ///
+ /// The SEALHeader to save to the stream
+ /// The stream to save the SEALHeader to
+ /// if header or stream is null
+ /// if the stream is closed or does not support writing
+ /// if I/O operations failed
+ public static void SaveHeader(SEALHeader header, Stream stream)
+ {
+ if (null == header)
+ throw new ArgumentNullException(nameof(header));
+ if (null == stream)
+ throw new ArgumentNullException(nameof(stream));
+ if (!stream.CanWrite)
+ throw new ArgumentException(nameof(stream));
+
+ using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true))
+ {
+ writer.Write(header.Magic);
+ writer.Write(header.HeaderSize);
+ writer.Write(header.VersionMajor);
+ writer.Write(header.VersionMinor);
+ writer.Write((byte)header.ComprMode);
+ writer.Write(header.Reserved);
+ writer.Write(header.Size);
+ }
+ }
+
+ /// Loads a SEALHeader from a given stream.
+ /// The stream to load the SEALHeader from
+ /// The SEALHeader to populate with the loaded data
+ /// If the loaded SEALHeader is invalid, attempt to identify its format and
+ /// upgrade to the current SEALHeader version
+ /// if header or stream is null
+ /// if the stream is closed or does not support reading
+ /// if the loaded data is not a valid SEALHeader or if the loaded
+ /// compression mode is not supported
+ /// if the stream ended unexpectedly
+ /// if I/O operations failed
+ public static void LoadHeader(Stream stream, SEALHeader header, bool tryUpgradeIfInvalid = true)
+ {
+ if (null == header)
+ throw new ArgumentNullException(nameof(header));
+ if (null == stream)
+ throw new ArgumentNullException(nameof(stream));
+ if (!stream.CanRead)
+ throw new ArgumentException(nameof(stream));
+
+ using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true))
+ {
+ header.Magic = reader.ReadUInt16();
+ header.HeaderSize = reader.ReadByte();
+ header.VersionMajor = reader.ReadByte();
+ header.VersionMinor = reader.ReadByte();
+ header.ComprMode = (ComprModeType)reader.ReadByte();
+ header.Reserved = reader.ReadUInt16();
+ header.Size = reader.ReadUInt64();
+ }
+
+ // If header is invalid this may be an older header and we can try to automatically upgrade it
+ if (tryUpgradeIfInvalid && !IsValidHeader(header))
+ {
+ // Try interpret the data as a Microsoft SEAL 3.4 header
+ LegacyHeaders.SEALHeader_3_4 header_3_4 = new LegacyHeaders.SEALHeader_3_4(header);
+
+ SEALHeader newHeader = new SEALHeader();
+ // Copy over the fields; of course the result may not be valid depending on whether the input was a
+ // valid version 3.4 header
+ newHeader.ComprMode = header_3_4.ComprMode;
+ newHeader.Size = header_3_4.Size;
+
+ // Now validate the new header and discard if still not valid; something else is probably wrong
+ if (IsValidHeader(newHeader))
+ {
+ header.Set(newHeader);
+ }
+ }
+ }
+
+ internal delegate void SaveDelegate(
+ byte[] outptr, ulong size, byte comprMode, out long outBytes);
+
+ internal delegate void LoadDelegate(
+ byte[] inptr, ulong size, out long inBytes);
+
+ /// Saves data to a given binary stream.
+ ///
+ /// First this function allocates a buffer of size . The buffer is used by the
+ /// delegate that writes some number of bytes to the buffer and outputs (in
+ /// out-parameter) the number of bytes written (less than the size of the buffer). The contents of the buffer
+ /// are then written to and the function returns the output value of
+ /// . This function is intended only for internal use.
+ ///
+ /// The delegate that writes some number of bytes to a given buffer
+ /// An upper bound on the number of bytes that requires
+ /// The desired compression mode
+ /// The destination stream
+ /// if SaveData or stream is null
+ /// if the stream is closed or does not support writing, or if size is
+ /// negative or too large
+ /// if I/O operations failed
+ /// if the data to be saved is invalid, if compression mode is not
+ /// supported, or if compression failed
+ internal static long Save(SaveDelegate SaveData, long size,
+ ComprModeType comprMode, Stream stream)
+ {
+ if (null == stream)
+ throw new ArgumentNullException(nameof(stream));
+ if (null == SaveData)
+ throw new ArgumentNullException(nameof(SaveData));
+ if (!stream.CanWrite)
+ throw new ArgumentException(nameof(stream));
+ if (!IsSupportedComprMode(comprMode))
+ throw new InvalidOperationException("Unsupported compression mode");
+
+ try
+ {
+ int sizeInt = checked((int)size);
+ byte[] buffer = new byte[sizeInt];
+ SaveData(buffer, checked((ulong)sizeInt), (byte)comprMode, out long outBytes);
+ int intOutBytes = checked((int)outBytes);
+ using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true))
+ {
+ writer.Write(buffer, 0, intOutBytes);
+ }
+
+ // Clear the buffer for safety reasons
+ Array.Clear(buffer, 0, intOutBytes);
+
+ return outBytes;
+ }
+ catch (OverflowException ex)
+ {
+ throw new ArgumentException($"{nameof(size)} is out of bounds", ex);
+ }
+ }
+
+ /// Loads data from a given binary stream.
+ ///
+ /// This function calls the function to first load a object
+ /// from . The is then read from the
+ /// and a buffer of corresponding size is allocated. Next, the buffer is filled with
+ /// data read from and is called with the buffer as input,
+ /// which outputs (in out-parameter) the number bytes read from the buffer. This should match exactly the size
+ /// of the buffer. Finally, the function returns the output value of . This function
+ /// is intended only for internal use.
+ ///
+ /// The delegate that reads some number of bytes to a given buffer
+ /// The input stream
+ /// if LoadData or stream is null
+ /// if the stream is closed or does not support reading
+ /// if the stream ended unexpectedly
+ /// if I/O operations failed
+ /// if the loaded data is invalid, if the loaded compression mode is
+ /// not supported, or if size of the object is more than 2 GB
+ internal static long Load(LoadDelegate LoadData, Stream stream)
+ {
+ if (null == stream)
+ throw new ArgumentNullException(nameof(stream));
+ if (null == LoadData)
+ throw new ArgumentNullException(nameof(LoadData));
+ if (!stream.CanRead)
+ throw new ArgumentException(nameof(stream));
+
+ try
+ {
+ SEALHeader header = new SEALHeader();
+ var pos = stream.Position;
+ LoadHeader(stream, header);
+
+ // Check the validity of the header
+ if (!IsCompatibleVersion(header))
+ throw new InvalidOperationException("Incompatible version");
+ if (!IsSupportedComprMode(header.ComprMode))
+ throw new InvalidOperationException("Unsupported compression mode");
+ if (!IsValidHeader(header))
+ throw new InvalidOperationException("Loaded SEALHeader is invalid");
+ if (header.Size > checked((ulong)int.MaxValue))
+ throw new InvalidOperationException("Object size is larger than 2 GB");
+
+ int sizeInt = checked((int)header.Size);
+ stream.Seek(pos, SeekOrigin.Begin);
+
+ byte[] buffer = null;
+ using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true))
+ {
+ buffer = reader.ReadBytes(sizeInt);
+ }
+
+ LoadData(buffer, header.Size, out long outBytes);
+
+ // Clear the buffer for safety reasons
+ Array.Clear(buffer, 0, sizeInt);
+
+ return outBytes;
+ }
+ catch (OverflowException ex)
+ {
+ throw new InvalidOperationException("Size indicated by loaded SEALHeader is out of bounds", ex);
+ }
+ }
+ }
+
+ /// Class to contain header information for legacy headers.
+ public abstract class LegacyHeaders
+ {
+ /// Class to enable compatibility with Microsoft SEAL 3.4 headers.
+ [StructLayout(LayoutKind.Explicit, Size=16)]
+ public class SEALHeader_3_4 : ISettable, ISettable
+ {
+ /// SEALMagic
+ [FieldOffset(0)]public ushort Magic = Serialization.SEALMagic;
+
+ /// ZeroByte
+ [FieldOffset(2)]public byte ZeroByte = 0;
+
+ /// ComprModeType
+ [FieldOffset(3)]public ComprModeType ComprMode = Serialization.ComprModeDefault;
+
+ /// Size
+ [FieldOffset(4)]public uint Size = 0;
+
+ /// Reserved
+ [FieldOffset(8)]public ulong Reserved = 0;
+
+ /// Creates a new SEALHeader_3_4.
+ public SEALHeader_3_4()
+ {
+ }
+
+ ///
+ /// Constructs a new SEALHeader_3_4 by copying a given one.
+ ///
+ /// The SEALHeader_3_4 to copy from
+ /// if copy is null
+ public SEALHeader_3_4(Serialization.SEALHeader copy)
+ {
+ if (null == copy)
+ throw new ArgumentNullException(nameof(copy));
+
+ Set(copy);
+ }
+
+ /// Copies a given SEALHeader_3_4 to the current one.
+ /// The SEALHeader_3_4 to copy from
+ /// if assign is null
+ public void Set(SEALHeader_3_4 assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ Magic = assign.Magic;
+ ZeroByte = assign.ZeroByte;
+ ComprMode = assign.ComprMode;
+ Size = assign.Size;
+ Reserved = assign.Reserved;
+ }
+
+ /// Copies a given SEALHeader to the current one as a byte array.
+ /// The SEALHeader to copy from
+ /// if assign is null
+ public void Set(Serialization.SEALHeader assign)
+ {
+ if (null == assign)
+ throw new ArgumentNullException(nameof(assign));
+
+ GCHandle gch = GCHandle.Alloc(this, GCHandleType.Pinned);
+ Marshal.StructureToPtr(assign, gch.AddrOfPinnedObject(), false);
+ gch.Free();
+ }
+ };
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/ValCheck.cs b/bigpiseal3.5.1/dotnet/src/ValCheck.cs
new file mode 100644
index 0000000000000000000000000000000000000000..01565fbe998eff7a017e93ee64240349c4208b01
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/ValCheck.cs
@@ -0,0 +1,155 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// Static methods for object validity checking.
+ ///
+ public static class ValCheck
+ {
+ ///
+ /// Check whether the given plaintext is valid for a given SEALContext. If the
+ /// given SEALContext is not set, the encryption parameters are invalid, or the
+ /// plaintext data does not match the SEALContext, this function returns false.
+ /// Otherwise, returns true.
+ ///
+ /// The plaintext to check
+ /// The SEALContext
+ /// if either plaintext or context is null
+ public static bool IsValidFor(Plaintext plaintext, SEALContext context)
+ {
+ if (null == plaintext)
+ throw new ArgumentNullException(nameof(plaintext));
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.ValCheck_Plaintext_IsValidFor(plaintext.NativePtr, context.NativePtr, out bool result);
+ return result;
+ }
+
+ ///
+ /// Check whether the given ciphertext is valid for a given SEALContext. If the
+ /// given SEALContext is not set, the encryption parameters are invalid, or the
+ /// ciphertext data does not match the SEALContext, this function returns false.
+ /// Otherwise, returns true.
+ ///
+ /// The ciphertext to check
+ /// The SEALContext
+ /// if either ciphertext or context is null
+ public static bool IsValidFor(Ciphertext ciphertext, SEALContext context)
+ {
+ if (null == ciphertext)
+ throw new ArgumentNullException(nameof(ciphertext));
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.ValCheck_Ciphertext_IsValidFor(ciphertext.NativePtr, context.NativePtr, out bool result);
+ return result;
+ }
+
+ ///
+ /// Check whether the given secret key is valid for a given SEALContext. If the
+ /// given SEALContext is not set, the encryption parameters are invalid, or the
+ /// secret key data does not match the SEALContext, this function returns false.
+ /// Otherwise, returns true.
+ ///
+ /// The secret key to check
+ /// The SEALContext
+ /// if either secretKey or context is null
+ public static bool IsValidFor(SecretKey secretKey, SEALContext context)
+ {
+ if (null == secretKey)
+ throw new ArgumentNullException(nameof(secretKey));
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.ValCheck_SecretKey_IsValidFor(secretKey.NativePtr, context.NativePtr, out bool result);
+ return result;
+ }
+
+ ///
+ /// Check whether the given public key is valid for a given SEALContext. If the
+ /// given SEALContext is not set, the encryption parameters are invalid, or the
+ /// public key data does not match the SEALContext, this function returns false.
+ /// Otherwise, returns true.
+ ///
+ /// The public key to check
+ /// The SEALContext
+ /// if either publicKey or context is null
+ public static bool IsValidFor(PublicKey publicKey, SEALContext context)
+ {
+ if (null == publicKey)
+ throw new ArgumentNullException(nameof(publicKey));
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.ValCheck_PublicKey_IsValidFor(publicKey.NativePtr, context.NativePtr, out bool result);
+ return result;
+ }
+
+ ///
+ /// Check whether the given KSwitchKeys is valid for a given SEALContext. If the
+ /// given SEALContext is not set, the encryption parameters are invalid, or the
+ /// KSwitchKeys data does not match the SEALContext, this function returns false.
+ /// Otherwise, returns true.
+ ///
+ /// The KSwitchKeys to check
+ /// The SEALContext
+ /// if either kswitchKeys or context is null
+ public static bool IsValidFor(KSwitchKeys kswitchKeys, SEALContext context)
+ {
+ if (null == kswitchKeys)
+ throw new ArgumentNullException(nameof(kswitchKeys));
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.ValCheck_KSwitchKeys_IsValidFor(kswitchKeys.NativePtr, context.NativePtr, out bool result);
+ return result;
+ }
+
+ ///
+ /// Check whether the given RelinKeys is valid for a given SEALContext. If the
+ /// given SEALContext is not set, the encryption parameters are invalid, or the
+ /// RelinKeys data does not match the SEALContext, this function returns false.
+ /// Otherwise, returns true.
+ ///
+ /// The RelinKeys to check
+ /// The SEALContext
+ /// if either relinKeys or context is null
+ public static bool IsValidFor(RelinKeys relinKeys, SEALContext context)
+ {
+ if (null == relinKeys)
+ throw new ArgumentNullException(nameof(relinKeys));
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.ValCheck_RelinKeys_IsValidFor(relinKeys.NativePtr, context.NativePtr, out bool result);
+ return result;
+ }
+
+ ///
+ /// Check whether the given GaloisKeys is valid for a given SEALContext. If the
+ /// given SEALContext is not set, the encryption parameters are invalid, or the
+ /// GaloisKeys data does not match the SEALContext, this function returns false.
+ /// Otherwise, returns true.
+ ///
+ /// The GaloisKeys to check
+ /// The SEALContext
+ /// if either galoisKeys or context is null
+ public static bool IsValidFor(GaloisKeys galoisKeys, SEALContext context)
+ {
+ if (null == galoisKeys)
+ throw new ArgumentNullException(nameof(galoisKeys));
+ if (null == context)
+ throw new ArgumentNullException(nameof(context));
+
+ NativeMethods.ValCheck_GaloisKeys_IsValidFor(galoisKeys.NativePtr, context.NativePtr, out bool result);
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/bigpiseal3.5.1/dotnet/src/Version.cs b/bigpiseal3.5.1/dotnet/src/Version.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8e2e068d02181c923565fde882735752ebeaea2e
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/Version.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+using System.IO;
+using System.Text;
+
+namespace Microsoft.Research.SEAL
+{
+ ///
+ /// This class contains static methods for retrieving Microsoft SEAL's version numbers.
+ ///
+ ///
+ /// Use the name SEALVersion to distinguish it from System.Version.
+ ///
+ public static class SEALVersion
+ {
+ ///
+ /// Returns Microsoft SEAL's version number string.
+ ///
+ static public string Version => $"{SEALVersion.Major}.{SEALVersion.Minor}.{SEALVersion.Patch}";
+
+ ///
+ ///
+ /// Returns Microsoft SEAL's major version number.
+ ///
+ static public byte Major
+ {
+ get
+ {
+ NativeMethods.Version_Major(out byte result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns Microsoft SEAL's minor version number.
+ ///
+ static public byte Minor
+ {
+ get
+ {
+ NativeMethods.Version_Minor(out byte result);
+ return result;
+ }
+ }
+
+ ///
+ /// Returns Microsoft SEAL's patch version number.
+ ///
+ static public byte Patch
+ {
+ get
+ {
+ NativeMethods.Version_Patch(out byte result);
+ return result;
+ }
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/tools/DisposableObject.cs b/bigpiseal3.5.1/dotnet/src/tools/DisposableObject.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8900e9b620da88a8e566f7e47e17acf24f195bfc
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/tools/DisposableObject.cs
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+
+namespace Microsoft.Research.SEAL.Tools
+{
+ ///
+ /// Class that implements the Disposable pattern
+ ///
+ public class DisposableObject : IDisposable
+ {
+ ///
+ /// Derived classes should override this method to release managed resources.
+ ///
+ protected virtual void DisposeManagedResources()
+ {
+ }
+
+ ///
+ /// Derived classes should override this method to release native resources.
+ ///
+ protected virtual void DisposeNativeResources()
+ {
+ }
+
+ ///
+ /// Whether this object is disposed
+ ///
+ public bool IsDisposed
+ {
+ get
+ {
+ return disposedValue;
+ }
+ }
+
+ #region IDisposable Support
+
+ private bool disposedValue = false; // To detect redundant calls
+
+ private void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ DisposeManagedResources();
+ }
+
+ DisposeNativeResources();
+
+ disposedValue = true;
+ }
+ }
+
+ ///
+ /// DisposableObject destructor
+ ///
+ ~DisposableObject()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(false);
+ }
+
+ ///
+ /// This code is added to correctly implement the disposable pattern.
+ ///
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/tools/NativeObject.cs b/bigpiseal3.5.1/dotnet/src/tools/NativeObject.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f8090229db31068a378e062df3b57c5bbd7eecb8
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/tools/NativeObject.cs
@@ -0,0 +1,91 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using System;
+
+namespace Microsoft.Research.SEAL.Tools
+{
+ ///
+ /// Class that encapsulates the behavior of a class backed by a
+ /// pointer to a native object.
+ ///
+ /// In particular, this class encapsulates the correct disposal
+ /// of the native pointer.
+ ///
+ public abstract class NativeObject : DisposableObject
+ {
+ ///
+ /// Construct a NativeObject instance
+ ///
+ public NativeObject()
+ {
+ NativePtr = IntPtr.Zero;
+ owned_ = true;
+ }
+
+ ///
+ /// Construct a NativeObject instance initializing it with a pointer
+ /// to a native object.
+ ///
+ /// Pointer to native object.
+ /// Whether this instance owns the native pointer.
+ public NativeObject(IntPtr nativePtr, bool owned = true)
+ {
+ NativePtr = nativePtr;
+ owned_ = owned;
+ }
+
+ ///
+ /// Descendants should call the appropriate method to
+ /// destroy the backing native object.
+ ///
+ protected abstract void DestroyNativeObject();
+
+ ///
+ /// Destroy native object if necessary
+ ///
+ protected override void DisposeNativeResources()
+ {
+ base.DisposeNativeResources();
+
+ if (owned_ && !IntPtr.Zero.Equals(NativePtr))
+ {
+ DestroyNativeObject();
+ }
+
+ NativePtr = IntPtr.Zero;
+ }
+
+ ///
+ /// Get/Set pointer to native object
+ ///
+ internal IntPtr NativePtr
+ {
+ get
+ {
+ if (IsDisposed)
+ {
+ Type objType = this.GetType();
+ string objName = objType?.FullName ?? "Unknown object name";
+ throw new ObjectDisposedException(objName);
+ }
+
+ return nativePtr_;
+ }
+ set
+ {
+ nativePtr_ = value;
+ }
+ }
+
+ ///
+ /// Whether this instance owns the native pointer.
+ ///
+ private readonly bool owned_ = true;
+
+ ///
+ /// Pointer to native object
+ ///
+ private IntPtr nativePtr_ = IntPtr.Zero;
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/src/tools/Utilities.cs b/bigpiseal3.5.1/dotnet/src/tools/Utilities.cs
new file mode 100644
index 0000000000000000000000000000000000000000..777fa007c16af0e7fdfcb497adea34e82df0c3c9
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/src/tools/Utilities.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+namespace Microsoft.Research.SEAL.Tools
+{
+ static class Utilities
+ {
+ public static readonly int BitsPerUInt64 = 64;
+ public static readonly int BitsPerUInt8 = 8;
+
+ public static int DivideRoundUp(int value, int divisor)
+ {
+ return (value + divisor - 1) / divisor;
+ }
+
+ public static int ComputeArrayHashCode(ulong[] array)
+ {
+ const int hash_seed = 17;
+ const int hash_multiply = 23;
+ int hash = hash_seed;
+
+ unchecked
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ ulong value = array[i];
+ if (value != 0)
+ {
+ hash *= hash_multiply;
+ hash += (int)value;
+ value >>= 32;
+ hash *= hash_multiply;
+ hash += (int)value;
+ }
+ }
+ }
+
+ return hash;
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/tests/BatchEncoderTests.cs b/bigpiseal3.5.1/dotnet/tests/BatchEncoderTests.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5db6df61fff4706d57d4f8f3fc4a6b54e72d2e03
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/tests/BatchEncoderTests.cs
@@ -0,0 +1,264 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices.ComTypes;
+
+namespace SEALNetTest
+{
+ [TestClass]
+ public class BatchEncoderTests
+ {
+ [TestMethod]
+ public void EncodeULongTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+ parms.PolyModulusDegree = 64;
+ parms.CoeffModulus = CoeffModulus.Create(64, new int[]{ 60 });
+ parms.PlainModulus = new Modulus(257);
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+
+ BatchEncoder encoder = new BatchEncoder(context);
+
+ Assert.AreEqual(64ul, encoder.SlotCount);
+
+ List plainList = new List();
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ plainList.Add((ulong)i);
+ }
+
+ Plaintext plain = new Plaintext();
+ encoder.Encode(plainList, plain);
+
+ List plainList2 = new List();
+ encoder.Decode(plain, plainList2);
+
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
+ }
+
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ plainList[checked((int)i)] = 5;
+ }
+
+ encoder.Encode(plainList, plain);
+ Assert.AreEqual("5", plain.ToString());
+
+ encoder.Decode(plain, plainList2);
+
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
+ }
+
+ List shortList = new List();
+ for (ulong i = 0; i < 20; i++)
+ {
+ shortList.Add(i);
+ }
+
+ encoder.Encode(shortList, plain);
+
+ List shortList2 = new List();
+ encoder.Decode(plain, shortList2);
+
+ Assert.AreEqual(20, shortList.Count);
+ Assert.AreEqual(64, shortList2.Count);
+
+ for (int i = 0; i < 20; i++)
+ {
+ Assert.AreEqual(shortList[i], shortList2[i]);
+ }
+
+ for (ulong i = 20; i < encoder.SlotCount; i++)
+ {
+ Assert.AreEqual(0ul, shortList2[checked((int)i)]);
+ }
+ }
+
+ [TestMethod]
+ public void EncodeLongTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV);
+ parms.PolyModulusDegree = 64;
+ parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 60 });
+ parms.PlainModulus = new Modulus(257);
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+
+ BatchEncoder encoder = new BatchEncoder(context);
+
+ Assert.AreEqual(64ul, encoder.SlotCount);
+
+ List plainList = new List();
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ plainList.Add((long)i);
+ }
+
+ Plaintext plain = new Plaintext();
+ encoder.Encode(plainList, plain);
+
+ List plainList2 = new List();
+ encoder.Decode(plain, plainList2);
+
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
+ }
+
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ plainList[checked((int)i)] = 5;
+ }
+
+ encoder.Encode(plainList, plain);
+ Assert.AreEqual("5", plain.ToString());
+
+ encoder.Decode(plain, plainList2);
+
+ for (ulong i = 0; i < encoder.SlotCount; i++)
+ {
+ Assert.AreEqual(plainList[checked((int)i)], plainList2[checked((int)i)]);
+ }
+
+ List shortList = new List();
+ for (int i = 0; i < 20; i++)
+ {
+ shortList.Add((long)i);
+ }
+
+ encoder.Encode(shortList, plain);
+
+ List shortList2 = new List();
+ encoder.Decode(plain, shortList2);
+
+ Assert.AreEqual(20, shortList.Count);
+ Assert.AreEqual(64, shortList2.Count);
+
+ for (int i = 0; i < 20; i++)
+ {
+ Assert.AreEqual(shortList[i], shortList2[i]);
+ }
+
+ for (ulong i = 20; i < encoder.SlotCount; i++)
+ {
+ Assert.AreEqual(0L, shortList2[checked((int)i)]);
+ }
+ }
+
+ [TestMethod]
+ public void EncodeInPlaceTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
+ {
+ PolyModulusDegree = 64,
+ CoeffModulus = CoeffModulus.Create(64, new int[] { 60 }),
+ PlainModulus = new Modulus(257)
+ };
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+
+ BatchEncoder encoder = new BatchEncoder(context);
+
+ Assert.AreEqual(64ul, encoder.SlotCount);
+
+ Plaintext plain = new Plaintext("6x^5 + 5x^4 + 4x^3 + 3x^2 + 2x^1 + 1");
+ Assert.AreEqual(6ul, plain.CoeffCount);
+
+ encoder.Encode(plain);
+
+ Assert.AreEqual(64ul, plain.CoeffCount);
+
+ encoder.Decode(plain);
+ Assert.AreEqual(64ul, plain.CoeffCount);
+
+ for (ulong i = 0; i < 6; i++)
+ {
+ Assert.AreEqual((i + 1), plain[i]);
+ }
+
+ for (ulong i = 6; i < plain.CoeffCount; i++)
+ {
+ Assert.AreEqual(0ul, plain[i]);
+ }
+ }
+
+ [TestMethod]
+ public void SchemeIsCKKSTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
+ {
+ PolyModulusDegree = 8,
+ CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40, 40, 40 })
+ };
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+
+ Utilities.AssertThrows(() =>
+ {
+ BatchEncoder encoder = new BatchEncoder(context);
+ });
+ }
+
+ [TestMethod]
+ public void ExceptionsTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
+ {
+ PolyModulusDegree = 64,
+ CoeffModulus = CoeffModulus.Create(64, new int[] { 60 }),
+ PlainModulus = new Modulus(257)
+ };
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+ BatchEncoder enc = new BatchEncoder(context);
+ List valu = new List();
+ List valu_null = null;
+ List vall = new List();
+ List vall_null = null;
+ Plaintext plain = new Plaintext();
+ Plaintext plain_null = null;
+ MemoryPoolHandle pool_uninit = new MemoryPoolHandle();
+
+ Utilities.AssertThrows(() => enc = new BatchEncoder(null));
+
+ Utilities.AssertThrows(() => enc.Encode(valu, plain_null));
+ Utilities.AssertThrows(() => enc.Encode(valu_null, plain));
+
+ Utilities.AssertThrows(() => enc.Encode(vall, plain_null));
+ Utilities.AssertThrows(() => enc.Encode(vall_null, plain));
+
+ Utilities.AssertThrows(() => enc.Encode(plain_null));
+ Utilities.AssertThrows(() => enc.Encode(plain, pool_uninit));
+
+ Utilities.AssertThrows(() => enc.Decode(plain, valu_null));
+ Utilities.AssertThrows(() => enc.Decode(plain_null, valu));
+ Utilities.AssertThrows(() => enc.Decode(plain, valu, pool_uninit));
+
+ Utilities.AssertThrows(() => enc.Decode(plain, vall_null));
+ Utilities.AssertThrows(() => enc.Decode(plain_null, vall));
+ Utilities.AssertThrows(() => enc.Decode(plain, vall, pool_uninit));
+
+ Utilities.AssertThrows(() => enc.Decode(plain_null));
+ Utilities.AssertThrows(() => enc.Decode(plain, pool_uninit));
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/tests/BigUIntTests.cs b/bigpiseal3.5.1/dotnet/tests/BigUIntTests.cs
new file mode 100644
index 0000000000000000000000000000000000000000..92162e414d241b6d0c14ee15cda5c5afdcf883b7
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/tests/BigUIntTests.cs
@@ -0,0 +1,985 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.IO;
+using System.Numerics;
+
+namespace SEALNetTest
+{
+ [TestClass]
+ public class BigUIntTests
+ {
+ [TestMethod]
+ public void EmptyConstructorTest()
+ {
+ BigUInt bui = new BigUInt();
+
+ Assert.IsTrue(bui.IsZero);
+ Assert.AreEqual(0, bui.BitCount);
+ }
+
+ [TestMethod]
+ public void BitCountConstructorTest()
+ {
+ BigUInt bui = new BigUInt(bitCount: 70);
+
+ Assert.IsTrue(bui.IsZero);
+ Assert.AreEqual(70, bui.BitCount);
+ Assert.AreEqual(2ul, bui.UInt64Count);
+ Assert.AreEqual(0, bui.GetSignificantBitCount());
+ }
+
+ [TestMethod]
+ public void HexStringConstructorTest()
+ {
+ BigUInt bui = new BigUInt("1234567890ABCDEF1234567890ABCDEF");
+
+ Assert.IsFalse(bui.IsZero);
+ Assert.AreEqual(2ul, bui.UInt64Count);
+ Assert.AreEqual(125, bui.BitCount);
+ Assert.AreEqual(125, bui.GetSignificantBitCount());
+
+ Assert.AreEqual(0x1234567890ABCDEFul, bui.Data(0));
+ Assert.AreEqual(0x1234567890ABCDEFul, bui.Data(1));
+
+ bui = new BigUInt("FEDCBAFEDCBA0987654321");
+
+ Assert.IsFalse(bui.IsZero);
+ Assert.AreEqual(2ul, bui.UInt64Count);
+ Assert.AreEqual(88, bui.BitCount);
+ Assert.AreEqual(88, bui.GetSignificantBitCount());
+
+ Assert.AreEqual(0xFEDCBAul, bui.Data(1));
+ Assert.AreEqual(0xFEDCBA0987654321ul, bui.Data(0));
+
+ bui = new BigUInt(bitCount: 80, hexString: "DEADBEEF");
+
+ Assert.IsFalse(bui.IsZero);
+ Assert.AreEqual(2ul, bui.UInt64Count);
+ Assert.AreEqual(80, bui.BitCount);
+ Assert.AreEqual(32, bui.GetSignificantBitCount());
+ Assert.AreEqual(0ul, bui.Data(1));
+ Assert.AreEqual(0xDEADBEEFul, bui.Data(0));
+ }
+
+ [TestMethod]
+ public void U64ConstructorTest()
+ {
+ BigUInt bui = new BigUInt(bitCount: 80, value: 12345ul);
+
+ Assert.IsFalse(bui.IsZero);
+ Assert.AreEqual(2ul, bui.UInt64Count);
+ Assert.AreEqual(14, bui.GetSignificantBitCount());
+ Assert.AreEqual(0ul, bui.Data(1));
+ Assert.AreEqual(12345ul, bui.Data(0));
+ }
+
+ [TestMethod]
+ public void BigIntegerConstructorTest()
+ {
+ BigInteger bi = new BigInteger(12345);
+ BigUInt bui = new BigUInt(bi);
+
+ Assert.IsFalse(bui.IsZero);
+ Assert.AreEqual(14, bui.BitCount);
+ Assert.AreEqual(2ul, bui.ByteCount);
+ Assert.AreEqual(14, bui.GetSignificantBitCount());
+ Assert.AreEqual(1ul, bui.UInt64Count);
+ Assert.AreEqual(12345ul, bui.Data(0));
+ }
+
+ [TestMethod]
+ public void CopyConstructorTest()
+ {
+ BigUInt bui1 = new BigUInt("DEADBEEF");
+ BigUInt bui2 = new BigUInt("1234567890ABCDEF1234567890ABCDEF");
+
+ BigUInt bui3 = new BigUInt(bui1);
+
+ Assert.AreEqual(1ul, bui3.UInt64Count);
+ Assert.AreEqual(32, bui3.GetSignificantBitCount());
+ Assert.AreEqual(0xDEADBEEFul, bui3.Data(0));
+ Assert.IsTrue(bui1.Equals(bui3));
+
+ bui3 = new BigUInt(bui2);
+
+ Assert.AreEqual(2ul, bui3.UInt64Count);
+ Assert.AreEqual(125, bui3.BitCount);
+ Assert.AreEqual(125, bui3.GetSignificantBitCount());
+ Assert.AreEqual(0x1234567890ABCDEFul, bui3.Data(0));
+ Assert.AreEqual(0x1234567890ABCDEFul, bui3.Data(1));
+ Assert.IsTrue(bui2.Equals(bui3));
+ }
+
+ [TestMethod]
+ public void EmptyBigUIntNET()
+ {
+ var biguint = new BigUInt();
+ Assert.AreEqual(0, biguint.BitCount);
+ Assert.AreEqual(0ul, biguint.ByteCount);
+ Assert.AreEqual(0ul, biguint.UInt64Count);
+ Assert.IsTrue(biguint.UInt64Count == 0ul);
+ Assert.AreEqual(0, biguint.GetSignificantBitCount());
+ Assert.AreEqual("0", biguint.ToString());
+ Assert.IsTrue(biguint.IsZero);
+ Assert.IsFalse(biguint.IsAlias);
+ biguint.SetZero();
+
+ var biguint2 = new BigUInt();
+ Assert.IsTrue(biguint.Equals(biguint2));
+
+ biguint.Resize(1);
+ Assert.AreEqual(1, biguint.BitCount);
+ Assert.IsTrue(biguint.UInt64Count != 0ul);
+ Assert.IsFalse(biguint.IsAlias);
+
+ biguint.Resize(0);
+ Assert.AreEqual(0, biguint.BitCount);
+ Assert.IsTrue(biguint.UInt64Count == 0ul);
+ Assert.IsFalse(biguint.IsAlias);
+ }
+
+ [TestMethod]
+ public void BigUInt64BitsNET()
+ {
+ var biguint = new BigUInt(64);
+ Assert.AreEqual(64, biguint.BitCount);
+ Assert.AreEqual(8ul, biguint.ByteCount);
+ Assert.AreEqual(1ul, biguint.UInt64Count);
+ Assert.AreEqual(0, biguint.GetSignificantBitCount());
+ Assert.AreEqual("0", biguint.ToString());
+ Assert.IsTrue(biguint.IsZero);
+ Assert.IsTrue(biguint.UInt64Count != 0);
+ Assert.AreEqual(0UL, biguint.Data(0));
+ Assert.AreEqual(0, biguint[0]);
+ Assert.AreEqual(0, biguint[1]);
+ Assert.AreEqual(0, biguint[2]);
+ Assert.AreEqual(0, biguint[3]);
+ Assert.AreEqual(0, biguint[4]);
+ Assert.AreEqual(0, biguint[5]);
+ Assert.AreEqual(0, biguint[6]);
+ Assert.AreEqual(0, biguint[7]);
+
+ biguint.Set(1);
+ Assert.AreEqual(1, biguint.GetSignificantBitCount());
+ Assert.AreEqual("1", biguint.ToString());
+ Assert.IsFalse(biguint.IsZero);
+ Assert.AreEqual(1UL, biguint.Data(0));
+ Assert.AreEqual(1, biguint[0]);
+ Assert.AreEqual(0, biguint[1]);
+ Assert.AreEqual(0, biguint[2]);
+ Assert.AreEqual(0, biguint[3]);
+ Assert.AreEqual(0, biguint[4]);
+ Assert.AreEqual(0, biguint[5]);
+ Assert.AreEqual(0, biguint[6]);
+ Assert.AreEqual(0, biguint[7]);
+ biguint.SetZero();
+ Assert.IsTrue(biguint.IsZero);
+ Assert.AreEqual(0UL, biguint.Data(0));
+
+ biguint.Set("7FFFFFFFFFFFFFFF");
+ Assert.AreEqual(63, biguint.GetSignificantBitCount());
+ Assert.IsFalse(biguint.IsZero);
+ Assert.AreEqual("7FFFFFFFFFFFFFFF", biguint.ToString());
+ Assert.AreEqual(0x7FFFFFFFFFFFFFFFUL, biguint.Data(0));
+ Assert.AreEqual(0xFF, biguint[0]);
+ Assert.AreEqual(0xFF, biguint[1]);
+ Assert.AreEqual(0xFF, biguint[2]);
+ Assert.AreEqual(0xFF, biguint[3]);
+ Assert.AreEqual(0xFF, biguint[4]);
+ Assert.AreEqual(0xFF, biguint[5]);
+ Assert.AreEqual(0xFF, biguint[6]);
+ Assert.AreEqual(0x7F, biguint[7]);
+
+ biguint.Set("FFFFFFFFFFFFFFFF");
+ Assert.AreEqual(64, biguint.GetSignificantBitCount());
+ Assert.IsFalse(biguint.IsZero);
+ Assert.AreEqual("FFFFFFFFFFFFFFFF", biguint.ToString());
+ Assert.AreEqual(0xFFFFFFFFFFFFFFFFUL, biguint.Data(0));
+ Assert.AreEqual(0xFF, biguint[0]);
+ Assert.AreEqual(0xFF, biguint[1]);
+ Assert.AreEqual(0xFF, biguint[2]);
+ Assert.AreEqual(0xFF, biguint[3]);
+ Assert.AreEqual(0xFF, biguint[4]);
+ Assert.AreEqual(0xFF, biguint[5]);
+ Assert.AreEqual(0xFF, biguint[6]);
+ Assert.AreEqual(0xFF, biguint[7]);
+
+ biguint.Set(0x8001);
+ Assert.AreEqual(16, biguint.GetSignificantBitCount());
+ Assert.AreEqual("8001", biguint.ToString());
+ Assert.AreEqual(0x8001UL, biguint.Data(0));
+ Assert.AreEqual(0x01, biguint[0]);
+ Assert.AreEqual(0x80, biguint[1]);
+ Assert.AreEqual(0x00, biguint[2]);
+ Assert.AreEqual(0x00, biguint[3]);
+ Assert.AreEqual(0x00, biguint[4]);
+ Assert.AreEqual(0x00, biguint[5]);
+ Assert.AreEqual(0x00, biguint[6]);
+ Assert.AreEqual(0x00, biguint[7]);
+ }
+
+ [TestMethod]
+ public void BigUInt99BitsNET()
+ {
+ var biguint = new BigUInt(99);
+ Assert.AreEqual(99, biguint.BitCount);
+ Assert.IsTrue(biguint.UInt64Count != 0ul);
+ Assert.AreEqual(13ul, biguint.ByteCount);
+ Assert.AreEqual(2ul, biguint.UInt64Count);
+ Assert.AreEqual(0, biguint.GetSignificantBitCount());
+ Assert.AreEqual("0", biguint.ToString());
+ Assert.IsTrue(biguint.IsZero);
+ Assert.AreEqual(0UL, biguint.Data(0));
+ Assert.AreEqual(0UL, biguint.Data(1));
+ Assert.AreEqual(0, biguint[0]);
+ Assert.AreEqual(0, biguint[1]);
+ Assert.AreEqual(0, biguint[2]);
+ Assert.AreEqual(0, biguint[3]);
+ Assert.AreEqual(0, biguint[4]);
+ Assert.AreEqual(0, biguint[5]);
+ Assert.AreEqual(0, biguint[6]);
+ Assert.AreEqual(0, biguint[7]);
+ Assert.AreEqual(0, biguint[8]);
+ Assert.AreEqual(0, biguint[9]);
+ Assert.AreEqual(0, biguint[10]);
+ Assert.AreEqual(0, biguint[11]);
+ Assert.AreEqual(0, biguint[12]);
+
+ biguint.Set(1);
+ Assert.AreEqual(1, biguint.GetSignificantBitCount());
+ Assert.AreEqual("1", biguint.ToString());
+ Assert.IsFalse(biguint.IsZero);
+ Assert.AreEqual(13ul, biguint.ByteCount);
+ Assert.AreEqual(2ul, biguint.UInt64Count);
+ Assert.AreEqual(1UL, biguint.Data(0));
+ Assert.AreEqual(0UL, biguint.Data(1));
+ Assert.AreEqual(1, biguint[0]);
+ Assert.AreEqual(0, biguint[1]);
+ Assert.AreEqual(0, biguint[2]);
+ Assert.AreEqual(0, biguint[3]);
+ Assert.AreEqual(0, biguint[4]);
+ Assert.AreEqual(0, biguint[5]);
+ Assert.AreEqual(0, biguint[6]);
+ Assert.AreEqual(0, biguint[7]);
+ Assert.AreEqual(0, biguint[8]);
+ Assert.AreEqual(0, biguint[9]);
+ Assert.AreEqual(0, biguint[10]);
+ Assert.AreEqual(0, biguint[11]);
+ Assert.AreEqual(0, biguint[12]);
+ biguint.SetZero();
+ Assert.IsTrue(biguint.IsZero);
+ Assert.AreEqual(0UL, biguint.Data(0));
+ Assert.AreEqual(0UL, biguint.Data(1));
+
+ biguint.Set("7FFFFFFFFFFFFFFFFFFFFFFFF");
+ Assert.AreEqual(99, biguint.GetSignificantBitCount());
+ Assert.AreEqual("7FFFFFFFFFFFFFFFFFFFFFFFF", biguint.ToString());
+ Assert.IsFalse(biguint.IsZero);
+ Assert.AreEqual(0xFFFFFFFFFFFFFFFFUL, biguint.Data(0));
+ Assert.AreEqual(0x7FFFFFFFFUL, biguint.Data(1));
+ Assert.AreEqual(0xFF, biguint[0]);
+ Assert.AreEqual(0xFF, biguint[1]);
+ Assert.AreEqual(0xFF, biguint[2]);
+ Assert.AreEqual(0xFF, biguint[3]);
+ Assert.AreEqual(0xFF, biguint[4]);
+ Assert.AreEqual(0xFF, biguint[5]);
+ Assert.AreEqual(0xFF, biguint[6]);
+ Assert.AreEqual(0xFF, biguint[7]);
+ Assert.AreEqual(0xFF, biguint[8]);
+ Assert.AreEqual(0xFF, biguint[9]);
+ Assert.AreEqual(0xFF, biguint[10]);
+ Assert.AreEqual(0xFF, biguint[11]);
+ Assert.AreEqual(0x07, biguint[12]);
+ biguint.SetZero();
+ Assert.IsTrue(biguint.IsZero);
+ Assert.AreEqual(0UL, biguint.Data(0));
+ Assert.AreEqual(0UL, biguint.Data(1));
+
+ biguint.Set("4000000000000000000000000");
+ Assert.AreEqual(99, biguint.GetSignificantBitCount());
+ Assert.AreEqual("4000000000000000000000000", biguint.ToString());
+ Assert.IsFalse(biguint.IsZero);
+ Assert.AreEqual(0UL, biguint.Data(0));
+ Assert.AreEqual(0x400000000UL, biguint.Data(1));
+ Assert.AreEqual(0, biguint[0]);
+ Assert.AreEqual(0, biguint[1]);
+ Assert.AreEqual(0, biguint[2]);
+ Assert.AreEqual(0, biguint[3]);
+ Assert.AreEqual(0, biguint[4]);
+ Assert.AreEqual(0, biguint[5]);
+ Assert.AreEqual(0, biguint[6]);
+ Assert.AreEqual(0, biguint[7]);
+ Assert.AreEqual(0, biguint[8]);
+ Assert.AreEqual(0, biguint[9]);
+ Assert.AreEqual(0, biguint[10]);
+ Assert.AreEqual(0, biguint[11]);
+ Assert.AreEqual(0x04, biguint[12]);
+
+ biguint.Set(0x8001);
+ Assert.AreEqual(16, biguint.GetSignificantBitCount());
+ Assert.AreEqual("8001", biguint.ToString());
+ Assert.IsFalse(biguint.IsZero);
+ Assert.AreEqual(0x8001UL, biguint.Data(0));
+ Assert.AreEqual(0UL, biguint.Data(1));
+ Assert.AreEqual(0x01, biguint[0]);
+ Assert.AreEqual(0x80, biguint[1]);
+ Assert.AreEqual(0, biguint[2]);
+ Assert.AreEqual(0, biguint[3]);
+ Assert.AreEqual(0, biguint[4]);
+ Assert.AreEqual(0, biguint[5]);
+ Assert.AreEqual(0, biguint[6]);
+ Assert.AreEqual(0, biguint[7]);
+ Assert.AreEqual(0, biguint[8]);
+ Assert.AreEqual(0, biguint[9]);
+ Assert.AreEqual(0, biguint[10]);
+ Assert.AreEqual(0, biguint[11]);
+ Assert.AreEqual(0, biguint[12]);
+
+ var biguint2 = new BigUInt("123");
+ Assert.IsFalse(biguint.Equals(biguint2));
+ Assert.IsFalse(biguint2.Equals(biguint));
+ Assert.AreNotEqual(biguint.GetHashCode(), biguint2.GetHashCode());
+
+ biguint.Set(biguint2);
+ Assert.IsTrue(biguint.Equals(biguint2));
+ Assert.IsTrue(biguint2.Equals(biguint));
+ Assert.AreEqual(biguint.GetHashCode(), biguint2.GetHashCode());
+ Assert.AreEqual(9, biguint.GetSignificantBitCount());
+ Assert.AreEqual("123", biguint.ToString());
+ Assert.AreEqual(0x123UL, biguint.Data(0));
+ Assert.AreEqual(0UL, biguint.Data(1));
+ Assert.AreEqual(0x23, biguint[0]);
+ Assert.AreEqual(0x01, biguint[1]);
+ Assert.AreEqual(0, biguint[2]);
+ Assert.AreEqual(0, biguint[3]);
+ Assert.AreEqual(0, biguint[4]);
+ Assert.AreEqual(0, biguint[5]);
+ Assert.AreEqual(0, biguint[6]);
+ Assert.AreEqual(0, biguint[7]);
+ Assert.AreEqual(0, biguint[8]);
+ Assert.AreEqual(0, biguint[9]);
+ Assert.AreEqual(0, biguint[10]);
+ Assert.AreEqual(0, biguint[11]);
+ Assert.AreEqual(0, biguint[12]);
+
+ biguint.Resize(8);
+ Assert.AreEqual(8, biguint.BitCount);
+ Assert.AreEqual(1ul, biguint.UInt64Count);
+ Assert.AreEqual("23", biguint.ToString());
+
+ biguint.Resize(100);
+ Assert.AreEqual(100, biguint.BitCount);
+ Assert.AreEqual(2ul, biguint.UInt64Count);
+ Assert.AreEqual("23", biguint.ToString());
+
+ biguint.Resize(0);
+ Assert.AreEqual(0, biguint.BitCount);
+ Assert.AreEqual(0ul, biguint.UInt64Count);
+ Assert.IsTrue(biguint.UInt64Count == 0);
+ }
+
+ [TestMethod]
+ public void SaveLoadUIntNET()
+ {
+ using (MemoryStream stream = new MemoryStream())
+ {
+ var value = new BigUInt();
+ var value2 = new BigUInt("100");
+ stream.Seek(0, SeekOrigin.Begin);
+ value.Save(stream);
+ stream.Seek(0, SeekOrigin.Begin);
+ value2.Load(stream);
+ Assert.AreEqual(value, value2);
+
+ value.Set("123");
+ stream.Seek(0, SeekOrigin.Begin);
+ value.Save(stream);
+ stream.Seek(0, SeekOrigin.Begin);
+ value2.Load(stream);
+ Assert.AreEqual(value, value2);
+
+ value.Set("FFFFFFFFFFFFFFFFFFFFFFFFFF");
+ stream.Seek(0, SeekOrigin.Begin);
+ value.Save(stream);
+ stream.Seek(0, SeekOrigin.Begin);
+ value2.Load(stream);
+ Assert.AreEqual(value, value2);
+
+ value.Set("0");
+ stream.Seek(0, SeekOrigin.Begin);
+ value.Save(stream);
+ stream.Seek(0, SeekOrigin.Begin);
+ value2.Load(stream);
+ Assert.AreEqual(value, value2);
+ }
+ }
+
+ [TestMethod]
+ public void DuplicateToNET()
+ {
+ var original = new BigUInt(123);
+ original.Set(56789);
+
+ var target = new BigUInt();
+
+ original.DuplicateTo(target);
+ Assert.AreEqual(target.BitCount, original.BitCount);
+ Assert.IsTrue(target.Equals(original));
+ }
+
+ [TestMethod]
+ public void DuplicateFromNET()
+ {
+ var original = new BigUInt(123);
+ original.Set(56789);
+
+ var target = new BigUInt();
+
+ target.DuplicateFrom(original);
+ Assert.AreEqual(target.BitCount, original.BitCount);
+ Assert.IsTrue(target.Equals(original));
+ }
+
+ [TestMethod]
+ public void ToBigIntegerTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigInteger bi = bui.ToBigInteger();
+ Assert.IsNotNull(bi);
+ Assert.IsFalse(bi.IsEven);
+ Assert.IsFalse(bi.IsZero);
+ Assert.AreEqual(0, bi.CompareTo(0xDEADBEEFul));
+ }
+
+ [TestMethod]
+ public void ToDecimalStringTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ string decStr = bui.ToDecimalString();
+ Assert.IsNotNull(decStr);
+ Assert.IsTrue("3735928559".Equals(decStr));
+ }
+
+ [TestMethod]
+ public void CompareToTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt other = new BigUInt("DEADBFFF");
+ Assert.IsTrue(bui.CompareTo(other) < 0);
+ Assert.IsTrue(other.CompareTo(bui) > 0);
+
+ BigUInt third = new BigUInt(bui);
+ Assert.AreNotSame(bui, third);
+ Assert.AreEqual(0, bui.CompareTo(third));
+ Assert.IsTrue(bui.CompareTo(null) > 0);
+ }
+
+ [TestMethod]
+ public void ModuloInvertFail1Test()
+ {
+ // Should fail when modulus is zero
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt mod = new BigUInt();
+
+ Assert.IsTrue(mod.IsZero);
+ Assert.IsFalse(bui.IsZero);
+
+ Utilities.AssertThrows(() => bui.ModuloInvert(mod));
+ }
+
+ [TestMethod]
+ public void ModuloInvertFail2Test()
+ {
+ // Should fail when modulus is not greater than the BigUInt value
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt mod = new BigUInt("BEEF");
+
+ Assert.IsFalse(mod.IsZero);
+ Assert.IsFalse(bui.IsZero);
+
+ Utilities.AssertThrows(() => bui.ModuloInvert(mod));
+ }
+
+ [TestMethod]
+ public void ModuloInvertFail3Test()
+ {
+ // Should fail when biguint value and modulus are not coprime
+ BigUInt bui = new BigUInt(bitCount: 64, value: 12);
+ BigUInt mod = new BigUInt(bitCount: 64, value: 24);
+
+ Assert.IsFalse(mod.IsZero);
+ Assert.IsFalse(bui.IsZero);
+
+ Utilities.AssertThrows(() => bui.ModuloInvert(mod));
+ }
+
+ [TestMethod]
+ public void ModuloInvertTest()
+ {
+ BigUInt bui = new BigUInt(bitCount: 64, value: 12);
+ BigUInt mod = new BigUInt(bitCount: 64, value: 25);
+
+ BigUInt inverse1 = bui.ModuloInvert(mod);
+
+ Assert.AreEqual(23ul, inverse1.Data(0));
+
+ BigUInt inverse2 = bui.ModuloInvert(modulus: 25ul);
+
+ Assert.AreEqual(23ul, inverse2.Data(0));
+ }
+
+ [TestMethod]
+ public void TryModuloInvertFail1Test()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt mod = new BigUInt();
+ BigUInt inverse = new BigUInt();
+
+ // Should fail when modulus is zero
+ Assert.IsTrue(mod.IsZero);
+ Utilities.AssertThrows(() => bui.TryModuloInvert(mod, inverse));
+ }
+
+ [TestMethod]
+ public void TryModuloInvertFail2Test()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt mod = new BigUInt("BEEF");
+ BigUInt inverse = new BigUInt();
+
+ // Should fail when biguint is bigger than modulus
+ Assert.IsFalse(mod.IsZero);
+ Utilities.AssertThrows(() => bui.TryModuloInvert(mod, inverse));
+ }
+
+ [TestMethod]
+ public void TryModuloInvertTest()
+ {
+ BigUInt bui = new BigUInt(bitCount: 64, value: 12);
+ BigUInt mod = new BigUInt(bitCount: 64, value: 25);
+ BigUInt inverse1 = new BigUInt();
+ BigUInt inverse2 = new BigUInt();
+
+ Assert.IsTrue(bui.TryModuloInvert(mod, inverse1));
+
+ Assert.AreEqual(23ul, inverse1.Data(0));
+
+ Assert.IsTrue(bui.TryModuloInvert(modulus: 25ul, inverse: inverse2));
+
+ Assert.AreEqual(23ul, inverse2.Data(0));
+
+ // Should fail (but not throw) when biguint value and modulus are not coprime
+ BigUInt bui2 = new BigUInt(bitCount: 64, value: 12);
+ BigUInt mod2 = new BigUInt(bitCount: 64, value: 24);
+
+ Assert.IsFalse(mod2.IsZero);
+ Assert.IsFalse(bui2.IsZero);
+
+ Assert.IsFalse(bui2.TryModuloInvert(mod2, inverse1));
+ }
+
+ [TestMethod]
+ public void DivideRemainderTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt op = new BigUInt("BEEF");
+ BigUInt remainder = new BigUInt();
+
+ BigUInt result = bui.DivideRemainder(op, remainder);
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0x12a90ul, result.Data(0));
+ Assert.AreEqual(1ul, remainder.UInt64Count);
+ Assert.AreEqual(0x227Ful, remainder.Data(0));
+
+ BigUInt result2 = bui.DivideRemainder(0xDEADul, remainder);
+
+ Assert.AreEqual(1ul, result2.UInt64Count);
+ Assert.AreEqual(0x10000ul, result2.Data(0));
+ Assert.AreEqual(1ul, remainder.UInt64Count);
+ Assert.AreEqual(0xBEEFul, remainder.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorPlusTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt newone = +bui;
+
+ Assert.AreEqual(1ul, newone.UInt64Count);
+ Assert.AreEqual(0xDEADBEEFul, newone.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorMinusTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt newone = -bui;
+
+ Assert.AreEqual(1ul, newone.UInt64Count);
+ Assert.AreEqual(0x21524111ul, newone.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorTildeTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt newone = ~bui;
+
+ Assert.AreEqual(1ul, newone.UInt64Count);
+ Assert.AreEqual(0x21524110ul, newone.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorPlusPlusTest()
+ {
+ BigUInt bui = new BigUInt("12345678901234567890");
+ bui++;
+
+ Assert.AreEqual(2ul, bui.UInt64Count);
+ Assert.AreEqual(0x1234ul, bui.Data(1));
+ Assert.AreEqual(0x5678901234567891ul, bui.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorMinusMinusTest()
+ {
+ BigUInt bui = new BigUInt("12345678901234567890");
+ bui--;
+
+ Assert.AreEqual(2ul, bui.UInt64Count);
+ Assert.AreEqual(0x1234ul, bui.Data(1));
+ Assert.AreEqual(0x567890123456788Ful, bui.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorAddTest()
+ {
+ BigUInt bui = new BigUInt("1234567890");
+ BigUInt op = new BigUInt("6543210");
+
+ BigUInt result = bui + op;
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0x123AAAAAA0ul, result.Data(0));
+
+ BigUInt result2 = bui + 0x9876543210ul;
+
+ Assert.AreEqual(1ul, result2.UInt64Count);
+ Assert.AreEqual(0xAAAAAAAAA0ul, result2.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorSubTest()
+ {
+ BigUInt bui = new BigUInt("1234567890");
+ BigUInt op = new BigUInt("6543210");
+
+ BigUInt result = bui - op;
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0x122E024680ul, result.Data(0));
+
+ result = bui - 0x76543210ul;
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0x11BE024680ul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorMultTest()
+ {
+ BigUInt bui = new BigUInt("12345");
+ BigUInt op = new BigUInt("ABCDEF");
+
+ BigUInt result = bui * op;
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0xC379652E6Bul, result.Data(0));
+
+ result = bui * 0xFEDCBAul;
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0x121F998EC22ul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorDivTest()
+ {
+ BigUInt bui = new BigUInt("1234567890");
+ BigUInt op = new BigUInt("BEEF");
+
+ BigUInt result = bui / op;
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0x18687Dul, result.Data(0));
+
+ result = bui / 0xDEAD;
+
+ Assert.AreEqual(1ul, result.UInt64Count);
+ Assert.AreEqual(0x14EDC6ul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorAndTest()
+ {
+ BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
+ BigUInt op = new BigUInt("FEFEFEFEFEFEFEFEFEFEFEFE");
+
+ BigUInt result = bui & op;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0xCCCCCCCCul, result.Data(1));
+ Assert.AreEqual(0xAAAAAAAAAAAAAAAAul, result.Data(0));
+
+ result = bui & 0xF0F0F0F0F0;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0ul, result.Data(1));
+ Assert.AreEqual(0xA0A0A0A0A0ul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorOrTest()
+ {
+ BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
+ BigUInt op = new BigUInt("E0E0E0E0E0E0E0E0E0E0E0E0");
+
+ BigUInt result = bui | op;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0xEDEDEDEDul, result.Data(1));
+ Assert.AreEqual(0xEBEBEBEBEBEBEBEBul, result.Data(0));
+
+ result = bui | 0x1010101010;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0xCDCDCDCDul, result.Data(1));
+ Assert.AreEqual(0xABABABBBBBBBBBBBul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorXorTest()
+ {
+ BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
+ BigUInt op = new BigUInt("0000FFFFFFFF000000000000");
+
+ BigUInt result = bui ^ op;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0xCDCD3232ul, result.Data(1));
+ Assert.AreEqual(0x5454ABABABABABABul, result.Data(0));
+
+ result = bui ^ 0xF0F0F0F0F0;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0xCDCDCDCDul, result.Data(1));
+ Assert.AreEqual(0xABABAB5B5B5B5B5Bul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorShiftLeftTest()
+ {
+ BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
+
+ BigUInt result = bui << 1;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0x19B9B9B9Bul, result.Data(1));
+ Assert.AreEqual(0x5757575757575756ul, result.Data(0));
+
+ result = bui << 2;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0x337373736ul, result.Data(1));
+ Assert.AreEqual(0xAEAEAEAEAEAEAEACul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorShiftRightTest()
+ {
+ BigUInt bui = new BigUInt("CDCDCDCDABABABABABABABAB");
+
+ BigUInt result = bui >> 1;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0x66E6E6E6ul, result.Data(1));
+ Assert.AreEqual(0xD5D5D5D5D5D5D5D5ul, result.Data(0));
+
+ result = bui >> 2;
+
+ Assert.AreEqual(2ul, result.UInt64Count);
+ Assert.AreEqual(0x33737373ul, result.Data(1));
+ Assert.AreEqual(0x6AEAEAEAEAEAEAEAul, result.Data(0));
+ }
+
+ [TestMethod]
+ public void OperatorDoubleTest()
+ {
+ BigUInt bui = new BigUInt("12345");
+
+ double value = (double)bui;
+
+ Assert.AreEqual(74565.0, value, delta: 0.1);
+
+ bui = new BigUInt("12345678901234567890");
+
+ value = (double)bui;
+
+ Assert.AreEqual(8.59680582719788E+22, value, delta: 3.5e7);
+ }
+
+ [TestMethod]
+ public void OperatorFloatTest()
+ {
+ BigUInt bui = new BigUInt("12345");
+ float value = (float)bui;
+
+ Assert.AreEqual(74565.0f, value, delta: 0.1);
+
+ bui.Set("12345678901234567890");
+
+ value = (float)bui;
+
+ Assert.AreEqual(8.59680582719788E+22f, value, delta: 0.1f);
+ }
+
+ [TestMethod]
+ public void OperatorUInt64Test()
+ {
+ BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF");
+ ulong value = (ulong)bui;
+
+ Assert.AreEqual(0x1234567890ABCDEFul, value);
+ }
+
+ [TestMethod]
+ public void OperatorInt64Test()
+ {
+ BigUInt bui = new BigUInt("ABCDEF124567890ABCDEF");
+ long value = (long)bui;
+
+ Assert.AreEqual(-1070635735584092689, value);
+ }
+
+ [TestMethod]
+ public void OperatorUInt32Test()
+ {
+ BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF");
+ uint value = (uint)bui;
+
+ Assert.AreEqual(0x90ABCDEFu, value);
+ }
+
+ [TestMethod]
+ public void OperatorInt32Test()
+ {
+ BigUInt bui = new BigUInt("ABCDEF1234567890ABCDEF");
+ int value = (int)bui;
+
+ Assert.AreEqual(-1867788817, value);
+ }
+
+ [TestMethod]
+ public void ExceptionsTest()
+ {
+ BigUInt bui = new BigUInt("DEADBEEF");
+ BigUInt bui1 = null;
+
+ Utilities.AssertThrows(() => bui1 = new BigUInt((BigUInt)null));
+ Utilities.AssertThrows(() => bui1 = new BigUInt((string)null));
+ Utilities.AssertThrows(() => bui1 = new BigUInt(bitCount: -1));
+ Utilities.AssertThrows(() => bui1 = new BigUInt(bitCount: 64, hexString: null));
+ Utilities.AssertThrows(() => bui1 = new BigUInt(bitCount: -1, hexString: "ABCDEF"));
+ Utilities.AssertThrows(() => bui1 = new BigUInt(bitCount: -1, value: 10ul));
+
+ bui1 = new BigUInt();
+ BigUInt bui2 = new BigUInt();
+
+ Utilities.AssertThrows(() => bui.Data(1));
+
+ Utilities.AssertThrows(() => bui[5] );
+ Utilities.AssertThrows(() => bui[5] = 2);
+
+ Utilities.AssertThrows(() => bui.DivideRemainder(bui1, null));
+ Utilities.AssertThrows(() => bui.DivideRemainder(null, bui2));
+ Utilities.AssertThrows(() => bui.DivideRemainder(bui1, bui2));
+
+ Utilities.AssertThrows(() => bui.DivideRemainder(1ul, null));
+ Utilities.AssertThrows(() => bui.DivideRemainder(0ul, bui2));
+
+ Utilities.AssertThrows(() => bui.DuplicateFrom(null));
+ Utilities.AssertThrows(() => bui.DuplicateTo(null));
+
+ Assert.IsFalse(bui.Equals(null));
+
+ Utilities.AssertThrows(() => bui.Load(null));
+ Utilities.AssertThrows(() => bui.ModuloInvert(null));
+ Utilities.AssertThrows(() => bui.Resize(bitCount: -1));
+ Utilities.AssertThrows(() => bui.Save(null));
+
+ Utilities.AssertThrows(() => bui.Set((BigUInt)null));
+ Utilities.AssertThrows(() => bui.Set((string)null));
+
+ Utilities.AssertThrows(() => bui.TryModuloInvert(bui1, null));
+ Utilities.AssertThrows(() => bui.TryModuloInvert(null, bui2));
+ Utilities.AssertThrows(() => bui.TryModuloInvert(bui1, bui2));
+ Utilities.AssertThrows(() => bui.TryModuloInvert(1ul, null));
+
+ bui2 = null;
+
+ Utilities.AssertThrows(() => bui2 = +bui2);
+ Utilities.AssertThrows(() => bui2 = -bui2);
+ Utilities.AssertThrows(() => bui2 = ~bui2);
+ Utilities.AssertThrows(() => bui2++);
+ Utilities.AssertThrows(() => bui2--);
+
+ Utilities.AssertThrows(() => bui1 = bui + bui2);
+ Utilities.AssertThrows(() => bui1 = bui2 + bui);
+ Utilities.AssertThrows(() => bui1 = bui2 + 1ul);
+
+ Utilities.AssertThrows(() => bui1 = bui - bui2);
+ Utilities.AssertThrows(() => bui1 = bui2 - bui);
+ Utilities.AssertThrows(() => bui1 = bui2 - 1ul);
+
+ Utilities.AssertThrows(() => bui1 = bui * bui2);
+ Utilities.AssertThrows(() => bui1 = bui2 * bui);
+ Utilities.AssertThrows(() => bui1 = bui2 * 1ul);
+
+ Utilities.AssertThrows(() => bui1 = bui / bui2);
+ Utilities.AssertThrows(() => bui1 = bui2 / bui);
+ Utilities.AssertThrows(() => bui1 = bui / bui1);
+ Utilities.AssertThrows(() => bui1 = bui2 / 1ul);
+ Utilities.AssertThrows(() => bui1 = bui / 0ul);
+
+ Utilities.AssertThrows(() => bui1 = bui ^ bui2);
+ Utilities.AssertThrows(() => bui1 = bui2 ^ bui);
+ Utilities.AssertThrows(() => bui1 = bui2 ^ 1ul);
+
+ Utilities.AssertThrows(() => bui1 = bui & bui2);
+ Utilities.AssertThrows(() => bui1 = bui2 & bui);
+ Utilities.AssertThrows(() => bui1 = bui2 & 1ul);
+
+ Utilities.AssertThrows(() => bui1 = bui | bui2);
+ Utilities.AssertThrows(() => bui1 = bui2 | bui);
+ Utilities.AssertThrows(() => bui1 = bui2 | 1ul);
+
+ Utilities.AssertThrows(() => bui1 = bui2 << 5);
+ Utilities.AssertThrows(() => bui1 = bui1 << -1);
+
+ Utilities.AssertThrows(() => bui1 = bui2 >> 5);
+ Utilities.AssertThrows(() => bui1 = bui1 >> -1);
+
+ Utilities.AssertThrows(() => { double d = (double)bui2; });
+ Utilities.AssertThrows(() => { float f = (float)bui2; });
+ Utilities.AssertThrows(() => { ulong u = (ulong)bui2; });
+ Utilities.AssertThrows(() => { long l = (long)bui2; });
+ Utilities.AssertThrows(() => { uint u = (uint)bui2; });
+ Utilities.AssertThrows(() => { int i = (int)bui2; });
+ }
+ }
+}
diff --git a/bigpiseal3.5.1/dotnet/tests/CKKSEncoderTests.cs b/bigpiseal3.5.1/dotnet/tests/CKKSEncoderTests.cs
new file mode 100644
index 0000000000000000000000000000000000000000..72d3bc0d398d09a1ead6714cab09096f7d4c3d3f
--- /dev/null
+++ b/bigpiseal3.5.1/dotnet/tests/CKKSEncoderTests.cs
@@ -0,0 +1,231 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Research.SEAL;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+
+namespace SEALNetTest
+{
+ [TestClass]
+ public class CKKSEncoderTests
+ {
+ [TestMethod]
+ public void EncodeDecodeDoubleTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+ parms.PolyModulusDegree = 64;
+ parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 });
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+
+ int slots = 16;
+ Plaintext plain = new Plaintext();
+ double delta = 1 << 16;
+ List result = new List();
+
+ CKKSEncoder encoder = new CKKSEncoder(context);
+ Assert.AreEqual(32ul, encoder.SlotCount);
+
+ double value = 10d;
+ encoder.Encode(value, delta, plain);
+ encoder.Decode(plain, result);
+
+ for (int i = 0; i < slots; i++)
+ {
+ double tmp = Math.Abs(value - result[i].Real);
+ Assert.IsTrue(tmp < 0.5);
+ }
+ }
+
+ [TestMethod]
+ public void EncodeDecodeUlongTest()
+ {
+
+ int slots = 32;
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+ parms.PolyModulusDegree = (ulong)slots * 2;
+ parms.CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 });
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+ CKKSEncoder encoder = new CKKSEncoder(context);
+
+ Plaintext plain = new Plaintext();
+ List result = new List();
+
+ long value = 15;
+ encoder.Encode(value, plain);
+ encoder.Decode(plain, result);
+
+ for (int i = 0; i < slots; i++)
+ {
+ double tmp = Math.Abs(value - result[i].Real);
+ Assert.IsTrue(tmp < 0.5);
+ }
+ }
+
+ [TestMethod]
+ public void EncodeDecodeComplexTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
+ {
+ PolyModulusDegree = 64,
+ CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40, 40, 40 })
+ };
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+ CKKSEncoder encoder = new CKKSEncoder(context);
+
+ Plaintext plain = new Plaintext();
+ Complex value = new Complex(3.1415, 2.71828);
+
+ encoder.Encode(value, scale: Math.Pow(2, 20), destination: plain);
+
+ List result = new List();
+ encoder.Decode(plain, result);
+
+ Assert.IsTrue(result.Count > 0);
+ Assert.AreEqual(3.1415, result[0].Real, delta: 0.0001);
+ Assert.AreEqual(2.71828, result[0].Imaginary, delta: 0.0001);
+ }
+
+ [TestMethod]
+ public void EncodeDecodeVectorTest()
+ {
+ int slots = 32;
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS);
+ parms.PolyModulusDegree = (ulong)slots * 2;
+ parms.CoeffModulus = CoeffModulus.Create((ulong)slots * 2, new int[] { 60, 60, 60, 60 });
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+ CKKSEncoder encoder = new CKKSEncoder(context);
+
+ List values = new List(slots);
+ Random rnd = new Random();
+ int dataBound = 1 << 30;
+ double delta = 1ul << 40;
+
+ for (int i = 0; i < slots; i++)
+ {
+ values.Add(new Complex(rnd.Next() % dataBound, 0));
+ }
+
+ Plaintext plain = new Plaintext();
+ encoder.Encode(values, delta, plain);
+
+ List result = new List();
+ encoder.Decode(plain, result);
+
+ for (int i = 0; i < slots; i++)
+ {
+ double tmp = Math.Abs(values[i].Real - result[i].Real);
+ Assert.IsTrue(tmp < 0.5);
+ }
+ }
+
+ [TestMethod]
+ public void EncodeDecodeVectorDoubleTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
+ {
+ PolyModulusDegree = 64,
+ CoeffModulus = CoeffModulus.Create(64, new int[] { 30, 30 })
+ };
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+ CKKSEncoder encoder = new CKKSEncoder(context);
+ Plaintext plain = new Plaintext();
+
+ double[] values = new double[] { 0.1, 2.3, 34.4 };
+ encoder.Encode(values, scale: Math.Pow(2, 20), destination: plain);
+
+ List result = new List();
+ encoder.Decode(plain, result);
+
+ Assert.IsNotNull(result);
+ Assert.AreEqual(0.1, result[0], delta: 0.001);
+ Assert.AreEqual(2.3, result[1], delta: 0.001);
+ Assert.AreEqual(34.4, result[2], delta: 0.001);
+ }
+
+ [TestMethod]
+ public void ExceptionsTest()
+ {
+ EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
+ {
+ PolyModulusDegree = 64,
+ CoeffModulus = CoeffModulus.Create(64, new int[] { 30, 30 })
+ };
+
+ SEALContext context = new SEALContext(parms,
+ expandModChain: false,
+ secLevel: SecLevelType.None);
+ CKKSEncoder encoder = new CKKSEncoder(context);
+ List vald = new List();
+ List