├── TFHE-examples ├── command.txt ├── output.txt └── README.md ├── BGV-BFV-examples └── openfhe │ ├── README.md │ └── BFV_BGV_tables.cpp ├── RNS-CKKS-examples ├── openfhe │ ├── README.md │ ├── FHE_table.cpp │ └── SHE_table.cpp └── lattigo │ ├── templates │ ├── basic │ │ ├── main_test.go │ │ └── main.go │ └── bootstrapping │ │ ├── main_test.go │ │ ├── failure │ │ ├── failure_probability.go │ │ └── table.go │ │ └── main.go │ ├── NOTICE │ ├── parameters │ ├── params_test.go │ ├── tables.go │ └── params.go │ ├── go.mod │ ├── README.md │ ├── go.sum │ └── LICENSE ├── max_logQ_tables.sh ├── .gitmodules ├── README.md ├── script.sh ├── functional-tables.py ├── max_logQ_tables.py └── tables.py /TFHE-examples/command.txt: -------------------------------------------------------------------------------- 1 | cargo run --release --quiet --bin v0-parameters -- $@ --p-error=5.421010862427522e-20 --min-precision=4 --max-precision=4 2 | 3 | -------------------------------------------------------------------------------- /BGV-BFV-examples/openfhe/README.md: -------------------------------------------------------------------------------- 1 | To run the scripts, clone OpenFHE v1.2.0, copy the *.cpp files to src/pke/examples, and build OpenFHE following the OpenFHE instructions. -------------------------------------------------------------------------------- /RNS-CKKS-examples/openfhe/README.md: -------------------------------------------------------------------------------- 1 | To run the scripts, clone OpenFHE v1.2.0, copy the *.cpp files to src/pke/examples, and build OpenFHE following the OpenFHE instructions. -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/templates/basic/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestMain(t *testing.T) { 6 | if testing.Short() { 7 | t.Skip("skipped in -short mode") 8 | } 9 | main() 10 | } 11 | -------------------------------------------------------------------------------- /max_logQ_tables.sh: -------------------------------------------------------------------------------- 1 | sage max_logQ_tables.py 128 0 2 | sage max_logQ_tables.py 192 0 3 | sage max_logQ_tables.py 256 0 4 | # sage max_logQ_tables.py 128 0 true 5 | # sage max_logQ_tables.py 192 0 true 6 | # sage max_logQ_tables.py 256 0 true 7 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/templates/bootstrapping/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | ) 7 | 8 | func TestMain(t *testing.T) { 9 | if testing.Short() { 10 | t.Skip("skipped in -short mode") 11 | } 12 | oldArgs := os.Args 13 | defer func() { os.Args = oldArgs }() 14 | os.Args = append(os.Args, "-short") 15 | main() 16 | } 17 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lattice-estimator"] 2 | path = lattice-estimator 3 | url = https://github.com/malb/lattice-estimator.git 4 | [submodule "TFHE-examples/concrete"] 5 | path = TFHE-examples/concrete 6 | url = https://github.com/zama-ai/concrete.git 7 | [submodule "concrete"] 8 | path = concrete 9 | url = https://github.com/zama-ai/concrete.git 10 | [submodule "BGV-BFV-examples/seal"] 11 | path = BGV-BFV-examples/seal 12 | url = https://github.com/WeiDaiWD/SEAL-Depth-Estimator.git 13 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2024 Jean-Philippe Bossuat, https://github.com/Pro7ech 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | this file except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | - [SageMath](https://www.sagemath.org/) 3 | 4 | ## How to Use 5 | ```bash 6 | git clone --recursive https://github.com/gong-cr/FHE-Security-Guidelines 7 | cd FHE-Security-Guidelines 8 | ``` 9 | 10 | For generating the table of maximum log Q, run the script: 11 | ```bash 12 | sh max_logQ_tables.sh 13 | ``` 14 | 15 | For example, 16 | ```bash 17 | sage max_logQ_tables.py 128 0 18 | ``` 19 | 20 | Here, 128 is the security threshold, and 0 is the security margin. The script outputts the maximum log Q that achieves the security target as 128 + 0. 21 | 22 | To test different parameters, edit in [max_logQ_tables.py](max_logQ_tables.py). -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/parameters/params_test.go: -------------------------------------------------------------------------------- 1 | package parameters 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/tuneinsight/lattigo/v5/he/hefloat" 7 | ) 8 | 9 | // TestExampleParams checks that all parameters listed 10 | // in ParametersInfosList meet their security target. 11 | func TestExampleParams(t *testing.T) { 12 | 13 | for _, paramsInfos := range ParametersInfosList { 14 | 15 | name := paramsInfos.Name 16 | 17 | t.Logf("%s\n", name) 18 | p, err := hefloat.NewParametersFromLiteral(ParametersList[name]) 19 | if err != nil { 20 | t.Fatal(err) 21 | } 22 | 23 | t.Log(Infos(p)) 24 | 25 | if err := AssertSecurity(p, paramsInfos.Lambda, paramsInfos.SecurityType); err != nil { 26 | t.Fatal(err) 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/go.mod: -------------------------------------------------------------------------------- 1 | module FHE-Security-Guidelines/RNS-CKKS-examples/lattigo 2 | 3 | go 1.22.0 4 | 5 | require ( 6 | github.com/tuneinsight/lattigo/v5 v5.0.3-0.20240126093303-0feb4f294f44 7 | gonum.org/v1/gonum v0.14.0 8 | ) 9 | 10 | require ( 11 | github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924 // indirect 12 | github.com/davecgh/go-spew v1.1.1 // indirect 13 | github.com/google/go-cmp v0.5.8 // indirect 14 | github.com/kr/text v0.2.0 // indirect 15 | github.com/pmezard/go-difflib v1.0.0 // indirect 16 | github.com/stretchr/testify v1.8.0 // indirect 17 | golang.org/x/crypto v0.18.0 // indirect 18 | golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect 19 | golang.org/x/sys v0.16.0 // indirect 20 | gopkg.in/yaml.v3 v3.0.1 // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/parameters/tables.go: -------------------------------------------------------------------------------- 1 | package parameters 2 | 3 | // TableClassicalTernary: Table 5.2 4 | var TableClassicalTernary = map[int]map[int]int{ 5 | 10: {128: 26}, 6 | 11: {128: 53, 192: 36, 256: 27}, 7 | 12: {128: 106, 192: 73, 256: 56}, 8 | 13: {128: 214, 192: 147, 256: 114}, 9 | 14: {128: 430, 192: 297, 256: 230}, 10 | 15: {128: 868, 192: 597, 256: 462}, 11 | 16: {128: 1747, 192: 1199, 256: 929}, 12 | 17: {128: 3523, 192: 2411, 256: 1866}, 13 | } 14 | 15 | // TableClassicalGaussian: Table 5.2 16 | var TableClassicalGaussian = map[int]map[int]int{ 17 | 10: {128: 28}, 18 | 11: {128: 55, 192: 38, 256: 30}, 19 | 12: {128: 108, 192: 75, 256: 58}, 20 | 13: {128: 216, 192: 149, 256: 119}, 21 | 14: {128: 432, 192: 299, 256: 232}, 22 | 15: {128: 870, 192: 599, 256: 464}, 23 | 16: {128: 1749, 192: 1201, 256: 931}, 24 | 17: {128: 3525, 192: 2413, 256: 1868}, 25 | } 26 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/README.md: -------------------------------------------------------------------------------- 1 | # FHE SECURIT GUIDELINES - RNS-CKKS - LATTIGO 2 | 3 | This is the complementary code to [Security Guidelines for Implementing Homomorphic Encryption](https://eprint.iacr.org/2024/463). 4 | 5 | It implements code for [Lattigo](https://github.com/tuneinsight/lattigo) to assert the security of `hefloat.Parameters`, provides example parameters and concrete instantiations of SHE and FHE CKKS instances, as well as methods to estimate the failure probability of the CKKS bootstrapping. 6 | 7 | ## SETUP 8 | 9 | 1. Install Go: https://go.dev/ 10 | 2. Check that Go was installed properly and added to the `PATH` with `$ go version` 11 | 3. Clone the repository https://github.com/gong-cr/FHE-Security-Guidelines 12 | 4. `$ cd RNS-CKKS-examples/lattigo` 13 | 5. `$ go test ./...` (this will run the tests and download all the dependencies) 14 | 15 | ## ORGANIZATION 16 | - `./parameters`: Methods and tables to assert the security of parameters. 17 | - `./templates/basic`: Example of parameters instantiation for SHE. 18 | - `./templates/bootstrapping`: Example of parameters instantiation for FHE. 19 | - `./templates/bootstrapping/failure`: Methods to estimate the bootstrapping failure probability and find suitable parameters for a target failure probability. 20 | 21 | ## RUNNING EXAMPLES 22 | 23 | To run a specific examples, go into the appropriate folder and `$ go run main.go`. 24 | For example, to run the FHE (`bootstrapping`) example: 25 | 1. `$ cd templates/bootstrapping` 26 | 2. `$ go run main.go` 27 | 28 | ## WARNING 29 | 30 | Some example might require up to ~24GB of RAM, documentation can be found at the top of each `main.go` file. -------------------------------------------------------------------------------- /TFHE-examples/output.txt: -------------------------------------------------------------------------------- 1 | security level: 128 2 | target p_error: 5.4e-20 3 | per precision and log norm2: 4 | 5 | - 4: # bits 6 | -ln2: k, N, n, br_l,br_b, ks_l,ks_b, cost, p_error 7 | - 0 : 1, 11, 805, 1, 23, 5, 3, 105, 4.1e-20 8 | - 1 : 1, 11, 805, 1, 23, 5, 3, 105, 4.4e-20 9 | - 2 : 1, 11, 806, 1, 23, 5, 3, 105, 3.9e-20 10 | - 3 : 1, 11, 809, 1, 23, 5, 3, 105, 3.9e-20 11 | - 4 : 1, 11, 826, 1, 23, 5, 3, 108, 5.1e-20 12 | - 5 : 1, 11, 805, 2, 15, 5, 3, 149, 4.0e-20 13 | - 6 : 1, 11, 805, 2, 15, 5, 3, 149, 4.0e-20 14 | - 7 : 1, 11, 805, 2, 15, 5, 3, 149, 4.1e-20 15 | - 8 : 1, 11, 805, 2, 15, 5, 3, 149, 4.2e-20 16 | - 9 : 1, 11, 805, 2, 15, 5, 3, 149, 5.0e-20 17 | - 10: 1, 11, 807, 2, 15, 5, 3, 149, 4.8e-20 18 | - 11: 1, 11, 817, 2, 15, 5, 3, 151, 4.3e-20 19 | - 12: 1, 11, 805, 3, 11, 5, 3, 193, 4.7e-20 20 | - 13: 1, 11, 806, 3, 11, 5, 3, 193, 5.2e-20 21 | - 14: 1, 11, 812, 3, 11, 5, 3, 195, 4.9e-20 22 | - 15: 1, 11, 816, 3, 11, 16, 1, 231, 5.3e-20 23 | - 16: 1, 11, 809, 4, 9, 5, 3, 238, 3.9e-20 24 | - 17: 1, 11, 793, 4, 9, 8, 2, 243, 5.2e-20 25 | - 18: 1, 11, 790, 5, 8, 8, 2, 285, 4.8e-20 26 | - 19: 1, 11, 794, 6, 7, 8, 2, 330, 4.3e-20 27 | - 20: 1, 11, 798, 7, 6, 8, 2, 375, 4.8e-20 28 | - 21: 1, 11, 821, 8, 5, 8, 2, 431, 5.4e-20 29 | - 22: 1, 11, 819, 11, 4, 17, 1, 593, 5.4e-20 30 | - 23: 1, 11, 799, 21, 2, 8, 2, 988, 4.7e-20 31 | # no solution starting from log norm2 = 24 32 | -------------------------------------------------------------------------------- /script.sh: -------------------------------------------------------------------------------- 1 | sage raw_data.py 128 matzov 32 test32 binary 2 | sage raw_data.py 128 matzov 32 test32 ternary 3 | sage raw_data.py 128 matzov 32 test32 gaussian 4 | 5 | sage raw_data.py 192 matzov 32 test32 binary 6 | sage raw_data.py 192 matzov 32 test32 ternary 7 | sage raw_data.py 192 matzov 32 test32 gaussian 8 | 9 | sage raw_data.py 256 matzov 32 test32 binary 10 | sage raw_data.py 256 matzov 32 test32 ternary 11 | sage raw_data.py 256 matzov 32 test32 gaussian 12 | 13 | sage raw_data.py 128 matzov 64 test64 binary 14 | sage raw_data.py 128 matzov 64 test64 ternary 15 | sage raw_data.py 128 matzov 64 test64 gaussian 16 | 17 | sage raw_data.py 192 matzov 64 test64 binary 18 | sage raw_data.py 192 matzov 64 test64 ternary 19 | sage raw_data.py 192 matzov 64 test64 gaussian 20 | 21 | sage raw_data.py 256 matzov 64 test64 binary 22 | sage raw_data.py 256 matzov 64 test64 ternary 23 | sage raw_data.py 256 matzov 64 test64 gaussian 24 | 25 | sage raw_data.py 128 quantum 32 test32 binary 26 | sage raw_data.py 128 quantum 32 test32 ternary 27 | sage raw_data.py 128 quantum 32 test32 gaussian 28 | 29 | sage raw_data.py 192 quantum 32 test32 binary 30 | sage raw_data.py 192 quantum 32 test32 ternary 31 | sage raw_data.py 192 quantum 32 test32 gaussian 32 | 33 | sage raw_data.py 256 quantum 32 test32 binary 34 | sage raw_data.py 256 quantum 32 test32 ternary 35 | sage raw_data.py 256 quantum 32 test32 gaussian 36 | 37 | sage raw_data.py 128 quantum 64 test64 binary 38 | sage raw_data.py 128 quantum 64 test64 ternary 39 | sage raw_data.py 128 quantum 64 test64 gaussian 40 | 41 | sage raw_data.py 192 quantum 64 test64 binary 42 | sage raw_data.py 192 quantum 64 test64 ternary 43 | sage raw_data.py 192 quantum 64 test64 gaussian 44 | 45 | sage raw_data.py 256 quantum 64 test64 binary 46 | sage raw_data.py 256 quantum 64 test64 ternary 47 | sage raw_data.py 256 quantum 64 test64 gaussian 48 | -------------------------------------------------------------------------------- /TFHE-examples/README.md: -------------------------------------------------------------------------------- 1 | To generate the output parameters, cd into `/FHE-Security-Guidelines/TFHE-examples/concrete/compilers/concrete-optimizer` and run the command in `command.txt`: 2 | 3 | ``` 4 | cargo run --release --quiet --bin v0-parameters -- $@ --p-error=5.421010862427522e-20 --min-precision=4 --max-precision=4 5 | ``` 6 | 7 | this will generate 128-bit secure parameters with a failure probability of `2^(-64)`, and you will recieve the output: 8 | 9 | ``` 10 | security level: 128 11 | target p_error: 5.4e-20 12 | per precision and log norm2: 13 | 14 | - 4: # bits 15 | -ln2: k, N, n, br_l,br_b, ks_l,ks_b, cost, p_error 16 | - 0 : 1, 11, 805, 1, 23, 5, 3, 105, 4.1e-20 17 | - 1 : 1, 11, 805, 1, 23, 5, 3, 105, 4.4e-20 18 | - 2 : 1, 11, 806, 1, 23, 5, 3, 105, 3.9e-20 19 | - 3 : 1, 11, 809, 1, 23, 5, 3, 105, 3.9e-20 20 | - 4 : 1, 11, 826, 1, 23, 5, 3, 108, 5.1e-20 21 | - 5 : 1, 11, 805, 2, 15, 5, 3, 149, 4.0e-20 22 | - 6 : 1, 11, 805, 2, 15, 5, 3, 149, 4.0e-20 23 | - 7 : 1, 11, 805, 2, 15, 5, 3, 149, 4.1e-20 24 | - 8 : 1, 11, 805, 2, 15, 5, 3, 149, 4.2e-20 25 | - 9 : 1, 11, 805, 2, 15, 5, 3, 149, 5.0e-20 26 | - 10: 1, 11, 807, 2, 15, 5, 3, 149, 4.8e-20 27 | - 11: 1, 11, 817, 2, 15, 5, 3, 151, 4.3e-20 28 | - 12: 1, 11, 805, 3, 11, 5, 3, 193, 4.7e-20 29 | - 13: 1, 11, 806, 3, 11, 5, 3, 193, 5.2e-20 30 | - 14: 1, 11, 812, 3, 11, 5, 3, 195, 4.9e-20 31 | - 15: 1, 11, 816, 3, 11, 16, 1, 231, 5.3e-20 32 | - 16: 1, 11, 809, 4, 9, 5, 3, 238, 3.9e-20 33 | - 17: 1, 11, 793, 4, 9, 8, 2, 243, 5.2e-20 34 | - 18: 1, 11, 790, 5, 8, 8, 2, 285, 4.8e-20 35 | - 19: 1, 11, 794, 6, 7, 8, 2, 330, 4.3e-20 36 | - 20: 1, 11, 798, 7, 6, 8, 2, 375, 4.8e-20 37 | - 21: 1, 11, 821, 8, 5, 8, 2, 431, 5.4e-20 38 | - 22: 1, 11, 819, 11, 4, 17, 1, 593, 5.4e-20 39 | - 23: 1, 11, 799, 21, 2, 8, 2, 988, 4.7e-20 40 | # no solution starting from log norm2 = 24 41 | ``` 42 | 43 | given in `output.txt`. 44 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/go.sum: -------------------------------------------------------------------------------- 1 | github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924 h1:DG4UyTVIujioxwJc8Zj8Nabz1L1wTgQ/xNBSQDfdP3I= 2 | github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924/go.mod h1:+NaH2gLeY6RPBPPQf4aRotPPStg+eXc8f9ZaE4vRfD4= 3 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 8 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 9 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 10 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 11 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 12 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 13 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 14 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 15 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 16 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 17 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 18 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 19 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 20 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 21 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 22 | github.com/tuneinsight/lattigo/v5 v5.0.3-0.20240126093303-0feb4f294f44 h1:MESsIHVrO/uivmBoRE5bXs3Rhqp+wqH2+EP4RDofFnA= 23 | github.com/tuneinsight/lattigo/v5 v5.0.3-0.20240126093303-0feb4f294f44/go.mod h1:6Wy7rxCBKLkOoEGT6Q4ueQ0wt1VvF6BtZwrpjVzp4Gw= 24 | golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= 25 | golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= 26 | golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= 27 | golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= 28 | golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= 29 | golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 30 | gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= 31 | gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= 32 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 33 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 34 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 35 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 36 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 37 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 38 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/parameters/params.go: -------------------------------------------------------------------------------- 1 | package parameters 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | 7 | "github.com/tuneinsight/lattigo/v5/he/hefloat" 8 | "github.com/tuneinsight/lattigo/v5/ring" 9 | "github.com/tuneinsight/lattigo/v5/utils" 10 | ) 11 | 12 | type SecurityType int 13 | 14 | const ( 15 | Classical = SecurityType(0) 16 | ) 17 | 18 | // AssertSecurity asserts the security of the provided [hefloat.Parameters] according to the 19 | // security parameter 2^{lambda} and security type [Classical]. 20 | // A descriptive error is returned if the parameters do not meet the target security. 21 | func AssertSecurity(p hefloat.Parameters, lambda int, securityType SecurityType) (err error) { 22 | 23 | var Table map[int]map[int]int 24 | 25 | switch Xs := p.Xs().(type) { 26 | case ring.Ternary: 27 | if Xs.P != 2.0/3 { 28 | return fmt.Errorf("unsupported ternary secret-key distribution: P should be 2/3 but is %f", Xs.P) 29 | } 30 | 31 | switch securityType { 32 | case Classical: 33 | Table = TableClassicalTernary 34 | default: 35 | return fmt.Errorf("unsupported SecurityType: should be Classical but is %v", securityType) 36 | } 37 | 38 | case ring.DiscreteGaussian: 39 | if Xs.Sigma != 3.19 { 40 | return fmt.Errorf("unsupported discret Gaussian secret-key distribution: sigma should be 3.19 but is %f", Xs.Sigma) 41 | } 42 | 43 | switch securityType { 44 | case Classical: 45 | Table = TableClassicalGaussian 46 | default: 47 | return fmt.Errorf("unsupported SecurityType: should be Classical but is %v", securityType) 48 | } 49 | 50 | default: 51 | return fmt.Errorf("unsupported secret-key distribution: should be ring.Ternary or ring.DiscreteGaussian") 52 | } 53 | 54 | if tableLogN, ok := Table[p.LogN()]; !ok { 55 | return fmt.Errorf("unsupported LogN: should be %v, but is %d", utils.GetSortedKeys(Table), p.LogN()) 56 | } else { 57 | if maxLogQP, ok := tableLogN[lambda]; !ok { 58 | return fmt.Errorf("unsupported lambda: should be %v, but is %d", utils.GetSortedKeys(Table[utils.GetSortedKeys(Table)[0]]), lambda) 59 | } else { 60 | if LogQP := math.Round(p.LogQP()); LogQP > float64(maxLogQP) { 61 | return fmt.Errorf("insecure parameters: p.LogQP() = %f > %f", LogQP, float64(maxLogQP)) 62 | } 63 | } 64 | } 65 | 66 | return 67 | } 68 | 69 | // Infos prints information about the parameters. 70 | func Infos(p hefloat.Parameters) string { 71 | return fmt.Sprintf(`LogN: %d 72 | Secret Key Distribution: %T - Density: %v 73 | Error Distribution: %T - Sigma: %v 74 | Base Prime Size: %d 75 | Available Multilications: %d 76 | Log2(PQ): %f 77 | Log2(Q): %f 78 | Log2(P): %f 79 | Log2(Scaling Factor): %d`, 80 | p.LogN(), 81 | p.Xs(), p.Xs().(ring.Ternary).P, 82 | p.Xe(), p.Xe().(ring.DiscreteGaussian).Sigma, 83 | int(math.Round(math.Log2(float64(p.Q()[0])))), 84 | p.MaxLevel(), 85 | p.LogQP(), 86 | p.LogQ(), 87 | p.LogP(), 88 | p.LogDefaultScale()) 89 | } 90 | 91 | // ParameterInfos is a struct storing informations about the parameters: 92 | // - Name: Params[N]Ternary[Classic][Lambda] 93 | // - Lambda: security (bits) of the parameters 94 | // - SecurityType: [Classical] 95 | type ParameterInfos struct { 96 | Name string 97 | Lambda int 98 | SecurityType SecurityType 99 | } 100 | 101 | // ParametersInfosList stores a list of example parameters 102 | // ranging from N=2^15 to N=2^16, classical and quantum secure 103 | // Lambda [128, 192, 256]. 104 | var ParametersInfosList = []ParameterInfos{ 105 | {"Params32768TernaryClassic128", 128, Classical}, 106 | {"Params32768TernaryClassic192", 192, Classical}, 107 | {"Params32768TernaryClassic256", 256, Classical}, 108 | {"Params65536TernaryClassic128", 128, Classical}, 109 | {"Params65536TernaryClassic192", 192, Classical}, 110 | {"Params65536TernaryClassic256", 256, Classical}, 111 | } 112 | 113 | // ParametersList is a list of example parameters stored in a map indexed 114 | // by their name that provide a concrete instantiation of the [ParameterInfos] 115 | // listed in [ParametersInfosList]. 116 | var ParametersList = map[string]hefloat.ParametersLiteral{ 117 | 118 | "Params32768TernaryClassic128": { 119 | LogN: 15, 120 | LogQ: []int{60, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, 121 | LogP: []int{61, 61, 61}, 122 | LogDefaultScale: 50, 123 | }, 124 | 125 | "Params32768TernaryClassic192": { 126 | LogN: 15, 127 | LogQ: []int{60, 50, 50, 50, 50, 50, 50, 50, 50}, 128 | LogP: []int{61, 61}, 129 | LogDefaultScale: 50, 130 | }, 131 | 132 | "Params32768TernaryClassic256": { 133 | LogN: 15, 134 | LogQ: []int{58, 48, 48, 48, 48, 48, 48}, 135 | LogP: []int{58, 58}, 136 | LogDefaultScale: 48, 137 | }, 138 | 139 | "Params65536TernaryClassic128": { 140 | LogN: 16, 141 | LogQ: []int{60, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, 142 | LogP: []int{54, 54, 54, 54, 54, 54}, 143 | LogDefaultScale: 50, 144 | }, 145 | 146 | "Params65536TernaryClassic192": { 147 | LogN: 16, 148 | LogQ: []int{60, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, 149 | LogP: []int{54, 54, 54, 54, 54}, 150 | LogDefaultScale: 50, 151 | }, 152 | 153 | "Params65536TernaryClassic256": { 154 | LogN: 16, 155 | LogQ: []int{60, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, 156 | LogP: []int{55, 55, 55, 54}, 157 | LogDefaultScale: 50, 158 | }, 159 | } 160 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/templates/basic/main.go: -------------------------------------------------------------------------------- 1 | // Package main is a template encrypted arithmetic with floating point values, with a set of example parameters, key generation, encoding, encryption, decryption and decoding. 2 | package main 3 | 4 | import ( 5 | "FHE-Security-Guidelines/RNS-CKKS-examples/lattigo/parameters" 6 | "fmt" 7 | "math" 8 | 9 | "github.com/tuneinsight/lattigo/v5/core/rlwe" 10 | "github.com/tuneinsight/lattigo/v5/he/hefloat" 11 | ) 12 | 13 | func main() { 14 | var err error 15 | var params hefloat.Parameters 16 | 17 | // The user has the complete freedom when instantiating RLWE cryptographic parameters. 18 | // Only minimal security checks are performed (e.g. that the secret distribution does not 19 | // lead to a zero key). 20 | // 21 | // It is therefor the responsibility of the user to ensure that the instantiated parameters 22 | // are compliant with the security standard. 23 | // 24 | // This example uses the `Params32768TernaryClassic128` which provide 128-bit secure 25 | // parameters against classical attacks for a ring degree of 2^{15}. 26 | 27 | paramsLit := parameters.ParametersList["Params32768TernaryClassic128"] 28 | // Optional (see lattigo/schemes/ckks/parameters.go): 29 | // - Xs: secret-key distribution (by default ring.Ternary{P:2.0/3}) 30 | // - Xe: error distribution (by default ring.DiscreteGaussian{Sigma:3.19, Bound:19}) 31 | // - LogNthRoot: n-th root used (by default LogN+1) 32 | // - RingType: 33 | // - ring.Standard (by default): Z[X]/(X^{N}+1), which enables up to N/2 complex slots 34 | // - ring.ConjugateInvariant: Z[X + X^{-1}]/(X^{N} + 1), which enables up to N real slots. 35 | // - Q: specify exact primes (instead of LogQ) 36 | // - P: specify exact primes (instead of LogP) 37 | 38 | if params, err = hefloat.NewParametersFromLiteral(paramsLit); err != nil { 39 | panic(err) 40 | } 41 | 42 | // Logs information about the parameters 43 | fmt.Printf("\n%s\n\n", parameters.Infos(params)) 44 | 45 | // Checks that the parameters are compliant with 128-bit classical security 46 | if err = parameters.AssertSecurity(params, 128, parameters.Classical); err != nil { 47 | panic(err) 48 | } 49 | 50 | // Key Generator 51 | kgen := rlwe.NewKeyGenerator(params) 52 | 53 | // Generate a Secret Key 54 | sk := kgen.GenSecretKeyNew() 55 | 56 | // Generate the Relinearization Key 57 | rlk := kgen.GenRelinearizationKeyNew(sk) 58 | 59 | // Galois elements for a cyclic rotation by 1 (to the left) and complex conjugation 60 | galEls := []uint64{params.GaloisElement(1), params.GaloisElementForComplexConjugation()} 61 | 62 | // Generates the Galois keys 63 | gks := kgen.GenGaloisKeysNew(galEls, sk) 64 | 65 | // Naive in memory EvaluationKeySet compliant to the [rlwe.EvaluationKeySet] interface. 66 | evk := rlwe.NewMemEvaluationKeySet(rlk, gks...) 67 | 68 | // Evaluator 69 | // Any struct implementing [rlwe.EvaluationKeySet] will be accepted for the keys. 70 | eval := hefloat.NewEvaluator(params, evk) 71 | 72 | // Encoder 73 | ecd := hefloat.NewEncoder(params) 74 | 75 | // Encryptor 76 | enc := rlwe.NewEncryptor(params, sk) 77 | 78 | // Decryptor 79 | dec := rlwe.NewDecryptor(params, sk) 80 | 81 | // Maximum number of slots (N/2) 82 | slots := params.MaxSlots() 83 | 84 | // Vector of plaintext values 85 | values := make([]complex128, slots) 86 | NthRoot := 32 87 | angle := 2 * 3.141592653589793 / float64(NthRoot) 88 | for i := range values { 89 | x := float64(i & (NthRoot - 1)) 90 | values[i] = complex(math.Cos(angle*x), math.Sin(angle*x)) 91 | } 92 | 93 | // Allocates a plaintext 94 | // Default rlwe.MetaData: 95 | // - IsBatched = true (slots encoding) 96 | // - Scale = params.DefaultScale() 97 | pt := hefloat.NewPlaintext(params, params.MaxLevel()) 98 | 99 | // Encodes the vector on the plaintext 100 | if err = ecd.Encode(values, pt); err != nil { 101 | panic(err) 102 | } 103 | 104 | // Encrypts the plaintext 105 | var ct *rlwe.Ciphertext 106 | if ct, err = enc.EncryptNew(pt); err != nil { 107 | panic(err) 108 | } 109 | 110 | // Dummy encrypted circuit 111 | // Multiplication with relinearization 112 | if err = eval.MulRelin(ct, ct, ct); err != nil { 113 | panic(err) 114 | } 115 | 116 | // Cyclic Rotation by 1 (to the left) 117 | if err = eval.Rotate(ct, 1, ct); err != nil { 118 | panic(err) 119 | } 120 | 121 | // Complex Conjugation 122 | if err = eval.Conjugate(ct, ct); err != nil { 123 | panic(err) 124 | } 125 | 126 | // Rescaling: consumes the last prime and 127 | // reduces the level by 1. 128 | if err = eval.Rescale(ct, ct); err != nil { 129 | panic(err) 130 | } 131 | 132 | // Dummy plaintext circuit 133 | want := make([]complex128, slots) 134 | copy(want, values) 135 | for i := range want { 136 | x := values[(i+1)&(slots-1)] 137 | y := x * x 138 | want[i] = complex(real(y), -imag(y)) 139 | } 140 | 141 | PrintPrecisionStats(params, ct, want, ecd, dec) 142 | } 143 | 144 | // PrintPrecisionStats decrypts, decodes and prints the precision stats of a ciphertext. 145 | func PrintPrecisionStats(params hefloat.Parameters, ct *rlwe.Ciphertext, want []complex128, ecd *hefloat.Encoder, dec *rlwe.Decryptor) { 146 | 147 | var err error 148 | 149 | // Decrypts the vector of plaintext values 150 | pt := dec.DecryptNew(ct) 151 | 152 | // Decodes the plaintext 153 | have := make([]complex128, ct.Slots()) 154 | if err = ecd.Decode(pt, have); err != nil { 155 | panic(err) 156 | } 157 | 158 | // Pretty prints some values 159 | fmt.Printf("Have: ") 160 | for i := 0; i < 4; i++ { 161 | fmt.Printf("%18.15f ", have[i]) 162 | } 163 | fmt.Printf("...\n") 164 | 165 | fmt.Printf("Want: ") 166 | for i := 0; i < 4; i++ { 167 | fmt.Printf("%18.15f ", want[i]) 168 | } 169 | fmt.Printf("...\n") 170 | 171 | // Pretty prints the precision stats 172 | fmt.Println(hefloat.GetPrecisionStats(params, ecd, dec, have, want, 0, false).String()) 173 | } 174 | -------------------------------------------------------------------------------- /BGV-BFV-examples/openfhe/BFV_BGV_tables.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================== 2 | // BSD 2-Clause License 3 | // 4 | // Copyright (c) 2014-2022, NJIT, Duality Technologies Inc. and other contributors 5 | // 6 | // All rights reserved. 7 | // 8 | // Author TPOC: contact@openfhe.org 9 | // 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are met: 12 | // 13 | // 1. Redistributions of source code must retain the above copyright notice, this 14 | // list of conditions and the following disclaimer. 15 | // 16 | // 2. Redistributions in binary form must reproduce the above copyright notice, 17 | // this list of conditions and the following disclaimer in the documentation 18 | // and/or other materials provided with the distribution. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | //================================================================================== 31 | 32 | /* 33 | Simple examples for CKKS without Bootstrapping, modified from simple-real-numbers.cpp provided by OpenFHE. 34 | */ 35 | 36 | #define PROFILE 37 | 38 | #include "openfhe.h" 39 | 40 | using namespace lbcrypto; 41 | void BFVExample(uint32_t multDepth, SecurityLevel secLevel, uint32_t numDigits, uint32_t plaintextModulus, 42 | uint32_t scalingModSize); 43 | void BGVExample(uint32_t multDepth, SecurityLevel secLevel, uint32_t numDigits, uint32_t plaintextModulus); 44 | 45 | int main(int argc, char* argv[]) { 46 | // SetII 47 | std::cout << "====================BFV Parameters====================" << std::endl; 48 | 49 | std::cout << "--------------------COLUMN 1--------------------" << std::endl; 50 | uint32_t multDepth = 10; 51 | SecurityLevel secLevel = HEStd_128_classic; 52 | uint32_t numDigits = 6; 53 | uint32_t plaintextModulus = 65537; 54 | uint32_t scalingModSize = 60; 55 | BFVExample(multDepth, secLevel, numDigits, plaintextModulus, scalingModSize); 56 | 57 | std::cout << "--------------------COLUMN 2--------------------" << std::endl; 58 | multDepth = 15; 59 | secLevel = HEStd_192_classic; 60 | numDigits = 9; 61 | plaintextModulus = 65537; 62 | scalingModSize = 59; 63 | BFVExample(multDepth, secLevel, numDigits, plaintextModulus, scalingModSize); 64 | 65 | std::cout << "--------------------COLUMN 3--------------------" << std::endl; 66 | multDepth = 18; 67 | secLevel = HEStd_256_classic; 68 | numDigits = 4; 69 | // finds the plaintext modulus that supports CRT packing for N = 2^{16} 70 | NativeInteger modulus = FirstPrime(16,1<<17); 71 | plaintextModulus = modulus.ConvertToInt(); 72 | scalingModSize = 60; 73 | BFVExample(multDepth, secLevel, numDigits, plaintextModulus, scalingModSize); 74 | 75 | std::cout << "====================BGV Parameters====================" << std::endl; 76 | 77 | std::cout << "--------------------COLUMN 1--------------------" << std::endl; 78 | multDepth = 8; 79 | secLevel = HEStd_128_classic; 80 | numDigits = 10; 81 | plaintextModulus = 65537; 82 | BGVExample(multDepth, secLevel, numDigits, plaintextModulus); 83 | 84 | std::cout << "--------------------COLUMN 2--------------------" << std::endl; 85 | multDepth = 13; 86 | secLevel = HEStd_192_classic; 87 | numDigits = 15; 88 | plaintextModulus = 65537; 89 | BGVExample(multDepth, secLevel, numDigits, plaintextModulus); 90 | 91 | std::cout << "--------------------COLUMN 3--------------------" << std::endl; 92 | multDepth = 15; 93 | secLevel = HEStd_256_classic; 94 | numDigits = 4; 95 | // uses the plaintext modulus that supports CRT packing for N = 2^{16} 96 | plaintextModulus = modulus.ConvertToInt(); 97 | 98 | BGVExample(multDepth, secLevel, numDigits, plaintextModulus); 99 | 100 | } 101 | void BFVExample(uint32_t multDepth, SecurityLevel secLevel, uint32_t numDigits, uint32_t plaintextModulus, 102 | uint32_t scalingModSize) { 103 | CCParams parameters; 104 | parameters.SetPlaintextModulus(plaintextModulus); 105 | parameters.SetMultiplicativeDepth(multDepth); 106 | parameters.SetKeySwitchTechnique(HYBRID); 107 | parameters.SetSecurityLevel(secLevel); 108 | parameters.SetNumLargeDigits(numDigits); 109 | parameters.SetScalingModSize(scalingModSize); 110 | 111 | CryptoContext cryptoContext = GenCryptoContext(parameters); 112 | 113 | const auto cryptoParams = std::dynamic_pointer_cast(cryptoContext->GetCryptoParameters()); 114 | 115 | std::cout << "Depth L = " << multDepth << std::endl; 116 | 117 | std::cout << "Plaintext modulus " << cryptoParams->GetPlaintextModulus() << std::endl; 118 | std::cout << "Ring dimension " << cryptoContext->GetRingDimension() << std::endl; 119 | std::cout << "Log Q " << cryptoContext->GetModulus().GetMSB() << std::endl; 120 | 121 | if (cryptoParams->GetKeySwitchTechnique() == HYBRID) { 122 | std::cout << "Log P " << cryptoParams->GetParamsP()->GetModulus().GetMSB() << std::endl; 123 | std::cout << "Log PQ " << cryptoParams->GetParamsQP()->GetModulus().GetMSB() << std::endl; 124 | } 125 | } 126 | 127 | void BGVExample(uint32_t multDepth, SecurityLevel secLevel, uint32_t numDigits, uint32_t plaintextModulus) { 128 | CCParams parameters; 129 | parameters.SetPlaintextModulus(plaintextModulus); 130 | parameters.SetMultiplicativeDepth(multDepth); 131 | parameters.SetKeySwitchTechnique(HYBRID); 132 | parameters.SetSecurityLevel(secLevel); 133 | parameters.SetNumLargeDigits(numDigits); 134 | 135 | CryptoContext cryptoContext = GenCryptoContext(parameters); 136 | 137 | const auto cryptoParams = std::dynamic_pointer_cast(cryptoContext->GetCryptoParameters()); 138 | 139 | std::cout << "Depth L = " << multDepth << std::endl; 140 | 141 | std::cout << "Plaintext modulus " << cryptoParams->GetPlaintextModulus() << std::endl; 142 | std::cout << "Ring dimension " << cryptoContext->GetRingDimension() << std::endl; 143 | std::cout << "Log Q " << cryptoContext->GetModulus().GetMSB() << std::endl; 144 | 145 | if (cryptoParams->GetKeySwitchTechnique() == HYBRID) { 146 | std::cout << "Log P " << cryptoParams->GetParamsP()->GetModulus().GetMSB() << std::endl; 147 | std::cout << "Log PQ " << cryptoParams->GetParamsQP()->GetModulus().GetMSB() << std::endl; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/templates/bootstrapping/failure/failure_probability.go: -------------------------------------------------------------------------------- 1 | package failure 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "math/big" 7 | 8 | "github.com/tuneinsight/lattigo/v5/ring" 9 | "github.com/tuneinsight/lattigo/v5/utils/bignum" 10 | ) 11 | 12 | // Probability returns the probability that PR[||I(X)|| > K]. 13 | // - Xs: secret distribution 14 | // - K: upper bound for I(X) 15 | // - logN: log2(ring degree) 16 | // - logSlots: log2(#complex slots) 17 | func Probability(Xs *ring.Ternary, K, logN, logSlots int) (logfailure float64) { 18 | 19 | // failureProbability returns PR[||I(X)|| > K] given 20 | // h: the Hamming weight of the secret 21 | // K: the upper bound of I(X) 22 | // logSlots: log2(#complex slots) 23 | 24 | if Xs.H != 0 && Xs.P != 0 { 25 | panic(fmt.Errorf("invalid Xs: Xs.H and Xs.P cannot both be non-zero")) 26 | } 27 | 28 | var c int 29 | var Eh int 30 | 31 | // If Xs is a probability density, then also takes into account 32 | // the correction factor of K. 33 | if Xs.P != 0 { 34 | 35 | prec := uint(256) 36 | 37 | N := math.Exp2(float64(logN)) 38 | Eh = int(math.Ceil(N*Xs.P) + 1) 39 | 40 | EhSqrt := math.Sqrt(float64(Eh)) 41 | s := math.Sqrt(1 - Xs.P) 42 | sqrt2 := math.Sqrt(2) 43 | 44 | // Binary search such that |PR[I(X) > K - c] - PR[h > E[h] + c/kappa * sigma(h)]| is small 45 | c = K >> 1 46 | step := c >> 1 47 | for step != 0 { 48 | 49 | kappa := float64(K-c) / EhSqrt 50 | d := float64(c) / (kappa * s) 51 | erfc := Log2ErfC(d/sqrt2, prec) 52 | fail := failureProbability(Eh, K-c, logSlots) 53 | 54 | if erfc > fail { 55 | c += step 56 | } else if erfc < fail { 57 | c -= step 58 | } else { 59 | break 60 | } 61 | 62 | step >>= 1 63 | } 64 | 65 | } else { 66 | Eh = Xs.H 67 | } 68 | 69 | return failureProbability(Eh, K-c, logSlots) 70 | } 71 | 72 | // failureProbability returns PR[||I(X)|| > K] given 73 | // h: the Hamming weight of the secret 74 | // K: the upper bound of I(X) 75 | // logSlots: log2(#complex slots) 76 | func failureProbability(h, K, logSlots int) (logfailure float64) { 77 | if h > 1024 { 78 | kappa := float64(K) / math.Sqrt(float64(h)) 79 | return F8192[int(math.Round(math.Sqrt(8192+1)*kappa))] + float64(logSlots+1) 80 | } 81 | 82 | return ModifiedIrwinHall(K, h, logSlots) 83 | } 84 | 85 | // FindSuitableK finds the smallest K such that PR[||I(X)|| > K] <= 2^{logfailure}. 86 | func FindSuitableK(Xs *ring.Ternary, logN, logSlots int, logfailure float64) (K int) { 87 | 88 | // getCorrectionFactor returns d such that 1-erf(d/sqrt(2)) 89 | // is close to 2^{logfailure}. 90 | getCorrectionFactor := func(logfailure float64) (d float64) { 91 | 92 | prec := uint(256) 93 | 94 | sqrt2 := math.Sqrt(2) 95 | 96 | d = 1.0 97 | for Log2ErfC(d/sqrt2, prec) > logfailure { 98 | d++ 99 | } 100 | 101 | step := d 102 | for step > 1e-3 { 103 | 104 | if Log2ErfC(d/sqrt2, prec) > logfailure { 105 | d += step 106 | } else { 107 | d -= step 108 | } 109 | 110 | step /= 2 111 | } 112 | 113 | return 114 | } 115 | 116 | findK := func(h, logSlots int, logfailure float64) (K int) { 117 | 118 | if h > 1024 { 119 | K = len(F8192) >> 1 120 | step := K >> 1 121 | for step > 0 { 122 | if F8192[K] > logfailure-float64(logSlots+1) { 123 | K += step 124 | } else if F8192[K] < logfailure-float64(logSlots+1) { 125 | K -= step 126 | } else { 127 | break 128 | } 129 | 130 | step >>= 1 131 | } 132 | 133 | for F8192[K] < logfailure-float64(logSlots+1) { 134 | K-- 135 | } 136 | 137 | for F8192[K] > logfailure-float64(logSlots+1) { 138 | K++ 139 | } 140 | 141 | kappa := float64(K) / math.Sqrt(float64(8192+1)) 142 | 143 | return int(math.Ceil(kappa * math.Sqrt(float64(h+1)))) 144 | } else { 145 | 146 | step := h >> 2 147 | K = h >> 1 148 | for step > 0 { 149 | 150 | if d := ModifiedIrwinHall(K, h, logSlots); d > logfailure { 151 | K += step 152 | } else if d < logfailure { 153 | K -= step 154 | } else { 155 | return 156 | } 157 | 158 | step >>= 1 159 | } 160 | 161 | for ModifiedIrwinHall(K, h, logSlots) < logfailure { 162 | K-- 163 | } 164 | 165 | for ModifiedIrwinHall(K, h, logSlots) > logfailure { 166 | K++ 167 | } 168 | 169 | return 170 | } 171 | 172 | } 173 | 174 | if Xs.H != 0 && Xs.P != 0 { 175 | panic(fmt.Errorf("invalid Xs: Xs.H and Xs.P cannot both be non-zero")) 176 | } 177 | 178 | if Xs.H != 0 { 179 | return findK(Xs.H, logSlots, logfailure) 180 | } 181 | 182 | // If Xs is a probability density, then also 183 | // adds a correction factor to K. 184 | N := math.Exp2(float64(logN)) 185 | 186 | Eh := math.Ceil(N*Xs.P) + 1 187 | 188 | K = findK(int(Eh), logSlots, logfailure) 189 | 190 | kappa := float64(K) / math.Sqrt(Eh) 191 | 192 | d := getCorrectionFactor(logfailure) 193 | 194 | return K + int(math.Ceil(d*kappa*math.Sqrt(1-Xs.P))) 195 | } 196 | 197 | // Log2ErfC returns log2(1 - erf(x)). 198 | func Log2ErfC(x float64, prec uint) (rF64 float64) { 199 | 200 | // Implements erfByEquation2 & erfcByEquation3 201 | // of "The functions erf and erfc computed with 202 | // arbitrary precision and explicit error bounds" 203 | // from S. Chevillard. 204 | N := int(prec) 205 | 206 | L := int(math.Ceil(math.Sqrt(float64(N)))) 207 | 208 | S := make([]*big.Float, L) 209 | for i := range S { 210 | S[i] = new(big.Float).SetPrec(prec) 211 | } 212 | 213 | xBig := new(big.Float).SetPrec(prec).SetFloat64(x) 214 | 215 | var y *big.Float 216 | 217 | t := 10.0 218 | 219 | if x > t { 220 | // acc <- x * x 221 | acc := new(big.Float).Mul(xBig, xBig) 222 | 223 | // y <- 1/(2*acc) 224 | y = new(big.Float).Add(acc, acc) 225 | y.Quo(new(big.Float).SetPrec(1), y) 226 | 227 | // acc <- exp(-acc) 228 | acc.Neg(acc) 229 | acc = bignum.Exp(acc) 230 | 231 | // tmp <- x * sqrt(pi) 232 | tmp := bignum.Pi(prec) 233 | tmp.Sqrt(tmp) 234 | tmp.Mul(xBig, tmp) 235 | 236 | // acc <- acc / tmp 237 | acc.Quo(acc, tmp) 238 | 239 | z := bignum.Pow(y, new(big.Float).SetPrec(prec).SetFloat64(float64(L))) 240 | 241 | for k, i := 0, 0; k <= N; k++ { 242 | 243 | if k&1 == 0 { 244 | S[i].Add(S[i], acc) 245 | } else { 246 | S[i].Sub(S[i], acc) 247 | } 248 | 249 | if i == L-1 { 250 | i = 0 251 | acc.Mul(acc, z) 252 | } else { 253 | i++ 254 | } 255 | 256 | acc.Mul(acc, new(big.Float).SetPrec(prec).SetInt64(int64(2*k-1))) 257 | } 258 | 259 | } else { 260 | 261 | // y <- 2 * x * x 262 | y = new(big.Float).Mul(xBig, xBig) 263 | y.Add(y, y) 264 | z := bignum.Pow(y, new(big.Float).SetPrec(prec).SetFloat64(float64(L))) 265 | 266 | // acc <- 2*x/sqrt(pi) 267 | acc := bignum.Pi(prec) 268 | acc.Sqrt(acc) 269 | acc.Quo(xBig, acc) 270 | acc.Add(acc, acc) 271 | 272 | // tmp <- exp(-x^2) 273 | tmp := new(big.Float).Mul(xBig, xBig) 274 | tmp.Neg(tmp) 275 | tmp = bignum.Exp(tmp) 276 | 277 | // acc <- 2*x/sqrt(pi) * exp(-x^2) 278 | acc.Mul(acc, tmp) 279 | 280 | for k, i := 1, 0; k <= N; k++ { 281 | S[i].Add(S[i], acc) 282 | 283 | if i == L-1 { 284 | i = 0 285 | acc.Mul(acc, z) 286 | } else { 287 | i++ 288 | } 289 | acc.Quo(acc, new(big.Float).SetPrec(prec).SetInt64(int64(2*k+1))) 290 | } 291 | } 292 | 293 | r := S[L-1] 294 | for i := L - 2; i >= 0; i-- { 295 | r.Mul(r, y) 296 | r.Add(r, S[i]) 297 | } 298 | 299 | if x <= t { 300 | r.Sub(new(big.Float).SetPrec(prec).SetInt64(1), r) 301 | } 302 | 303 | r = bignum.Log(r) 304 | r.Quo(r, bignum.Log2(prec)) 305 | 306 | rF64, _ = r.Float64() 307 | 308 | return rF64 309 | } 310 | -------------------------------------------------------------------------------- /functional-tables.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, 'lattice-estimator') 3 | from estimator import * 4 | 5 | classic_model = RC.BDGL16 6 | quantum_model = RC.LaaMosPol14 7 | 8 | # Table 5.4 BFV / BGV without bootstrapping 9 | 10 | bfvbgv_nobootstrap_16384_classic_128 = LWE.Parameters( 11 | n = 16384, 12 | q = 2**424, 13 | Xs = ND.UniformMod(3), 14 | Xe = ND.DiscreteGaussian(3.19), 15 | m = oo, 16 | tag = "bfvbgv_nobootstrap_16384_classic" 17 | ) 18 | 19 | bfvbgv_nobootstrap_16384_quantum_128 = LWE.Parameters( 20 | n = 16384, 21 | q = 2**391, 22 | Xs = ND.UniformMod(3), 23 | Xe = ND.DiscreteGaussian(3.19), 24 | m = oo, 25 | tag = "bfvbgv_nobootstrap_16384_quantum_128" 26 | ) 27 | 28 | bfvbgv_nobootstrap_32768_classic_192 = LWE.Parameters( 29 | n = 32768, 30 | q = 2**585, 31 | Xs = ND.UniformMod(3), 32 | Xe = ND.DiscreteGaussian(3.19), 33 | m = oo, 34 | tag = "bfvbgv_nobootstrap_32768_classic_192" 35 | ) 36 | 37 | bfvbgv_nobootstrap_32768_quantum_192 = LWE.Parameters( 38 | n = 32768, 39 | q = 2**562, 40 | Xs = ND.UniformMod(3), 41 | Xe = ND.DiscreteGaussian(3.19), 42 | m = oo, 43 | tag = "bfvbgv_nobootstrap_32768_quantum_192" 44 | ) 45 | 46 | bfvbgv_nobootstrap_65536_classic_256 = LWE.Parameters( 47 | n = 65536, 48 | q = 2**920, 49 | Xs = ND.UniformMod(3), 50 | Xe = ND.DiscreteGaussian(3.19), 51 | m = oo, 52 | tag = "bfvbgv_nobootstrap_65536_classic_256" 53 | ) 54 | 55 | bfvbgv_nobootstrap_65536_quantum_256 = LWE.Parameters( 56 | n = 65536, 57 | q = 2**880, 58 | Xs = ND.UniformMod(3), 59 | Xe = ND.DiscreteGaussian(3.19), 60 | m = oo, 61 | tag = "bfvbgv_nobootstrap_65536_quantum_256" 62 | ) 63 | 64 | Table_5_4 = [ 65 | (bfvbgv_nobootstrap_16384_classic_128, 128, classic_model), 66 | (bfvbgv_nobootstrap_16384_quantum_128, 128, quantum_model), 67 | (bfvbgv_nobootstrap_32768_classic_192, 192, classic_model), 68 | (bfvbgv_nobootstrap_32768_quantum_192, 192, quantum_model), 69 | (bfvbgv_nobootstrap_65536_classic_256, 256, classic_model), 70 | (bfvbgv_nobootstrap_65536_quantum_256, 256, quantum_model), 71 | ] 72 | 73 | # Table 5.5 74 | 75 | tfhe_742_classic_128 = LWE.Parameters( 76 | n = 742, 77 | q = 2**64, 78 | Xs = ND.UniformMod(2), 79 | Xe = ND.DiscreteGaussian(2**(-17.11) * 2**64), 80 | m = oo, 81 | tag = "param_functional_tfhe_742_binary_classic_128" 82 | ) 83 | 84 | tfhe_2048_classic_128 = LWE.Parameters( 85 | n = 2048, 86 | q = 2**64, 87 | Xs = ND.UniformMod(2), 88 | Xe = ND.DiscreteGaussian(2**(-51.6) * 2**64), 89 | m = oo, 90 | tag = "tfhe_2048_classic_128" 91 | ) 92 | 93 | tfhe_777_classic_128 = LWE.Parameters( 94 | n = 777, 95 | q = 2**64, 96 | Xs = ND.UniformMod(2), 97 | Xe = ND.DiscreteGaussian(2**(-18.03) * 2**64), 98 | m = oo, 99 | tag = "tfhe_777_classic_128" 100 | ) 101 | 102 | tfhe_1536_classic_128 = LWE.Parameters( 103 | n = 512 * 3, 104 | q = 2**64, 105 | Xs = ND.UniformMod(2), 106 | Xe = ND.DiscreteGaussian(2**(-38.08) * 2**64), 107 | m = oo, 108 | tag = "tfhe_1536_classic_128" 109 | ) 110 | 111 | tfhe_630_classic_128 = LWE.Parameters( 112 | n = 630, 113 | q = 2**32, 114 | Xs = ND.UniformMod(2), 115 | Xe = ND.DiscreteGaussian(2**(-15) * 2**32), 116 | m = oo, 117 | tag = "tfhe_630_classic_128") 118 | 119 | 120 | tfhe_1024_classic_128 = LWE.Parameters( 121 | n = 1024, 122 | q = 2**32, 123 | Xs = ND.UniformMod(2), 124 | Xe = ND.DiscreteGaussian(2**(-25) * 2**32), 125 | m = oo, 126 | tag = "tfhe_1024_classic_128") 127 | 128 | tfhe_512_classic_128 = LWE.Parameters( 129 | n = 512, 130 | q = 2**14, 131 | Xs = ND.UniformMod(3), 132 | Xe = ND.DiscreteGaussian(3.2), 133 | m = oo, 134 | tag = "tfhe_512_classic_128") 135 | 136 | tfhe_1024_classic_128_27 = LWE.Parameters( 137 | n = 1024, 138 | q = 2**27, 139 | Xs = ND.UniformMod(3), 140 | Xe = ND.DiscreteGaussian(3.2), 141 | m = oo, 142 | tag = "tfhe_1024_classic_128_27") 143 | 144 | Table_5_5 = [ 145 | (tfhe_742_classic_128, 128, classic_model), 146 | (tfhe_2048_classic_128, 128, classic_model), 147 | (tfhe_777_classic_128, 128, classic_model), 148 | (tfhe_1536_classic_128, 128, classic_model), 149 | (tfhe_630_classic_128, 128, classic_model), 150 | (tfhe_1024_classic_128, 128, classic_model), 151 | (tfhe_512_classic_128, 128, classic_model), 152 | (tfhe_1024_classic_128_27, 128, classic_model) 153 | ] 154 | 155 | #Table 5.6 156 | 157 | ckks_nobootstrap_16384_classic_128 = LWE.Parameters( 158 | n = 16384, 159 | q = 2**426, 160 | Xs = ND.UniformMod(3), 161 | Xe = ND.DiscreteGaussian(3.19), 162 | m = oo, 163 | tag = "ckks_nobootstrap_16384_classic_128" 164 | ) 165 | 166 | ckks_nobootstrap_32768_classic_192 = LWE.Parameters( 167 | n = 32768, 168 | q = 2**602, 169 | Xs = ND.UniformMod(3), 170 | Xe = ND.DiscreteGaussian(3.19), 171 | m = oo, 172 | tag = "ckks_nobootstrap_32768_classic_192" 173 | ) 174 | 175 | ckks_nobootstrap_32768_classic_256 = LWE.Parameters( 176 | n = 32768, 177 | q = 2**472, 178 | Xs = ND.UniformMod(3), 179 | Xe = ND.DiscreteGaussian(3.19), 180 | m = oo, 181 | tag = "ckks_nobootstrap_32768_classic_256" 182 | ) 183 | 184 | ckks_nobootstrap_16384_quantum_128 = LWE.Parameters( 185 | n = 16384, 186 | q = 2**388, 187 | Xs = ND.UniformMod(3), 188 | Xe = ND.DiscreteGaussian(3.19), 189 | m = oo, 190 | tag = "ckks_nobootstrap_16384_classic_128" 191 | ) 192 | 193 | ckks_nobootstrap_32768_quantum_192 = LWE.Parameters( 194 | n = 32768, 195 | q = 2**560, 196 | Xs = ND.UniformMod(3), 197 | Xe = ND.DiscreteGaussian(3.19), 198 | m = oo, 199 | tag = "ckks_nobootstrap_32768_classic_192" 200 | ) 201 | 202 | ckks_nobootstrap_32768_quantum_256 = LWE.Parameters( 203 | n = 32768, 204 | q = 2**434, 205 | Xs = ND.UniformMod(3), 206 | Xe = ND.DiscreteGaussian(3.19), 207 | m = oo, 208 | tag = "ckks_nobootstrap_32768_classic_256" 209 | ) 210 | 211 | Table_5_6 = [ 212 | (ckks_nobootstrap_16384_classic_128, 128, classic_model), 213 | (ckks_nobootstrap_32768_classic_192, 192, classic_model), 214 | (ckks_nobootstrap_32768_classic_256, 256, classic_model), 215 | (ckks_nobootstrap_16384_quantum_128, 128, quantum_model), 216 | (ckks_nobootstrap_32768_quantum_192, 192, quantum_model), 217 | (ckks_nobootstrap_32768_quantum_256, 256, quantum_model), 218 | ] 219 | 220 | 221 | #Table 5.7 222 | 223 | ckks_bootstrap_65536_classic_128_1 = LWE.Parameters( 224 | n = 65536, 225 | q = 2**1769, 226 | Xs = ND.UniformMod(3), 227 | Xe = ND.DiscreteGaussian(3.19), 228 | m = oo, 229 | tag = "ckks_bootstrap_65536_classic_128" 230 | ) 231 | 232 | ckks_bootstrap_65536_classic_128_2 = LWE.Parameters( 233 | n = 65536, 234 | q = 2**1750, 235 | Xs = ND.UniformMod(3), 236 | Xe = ND.DiscreteGaussian(3.19), 237 | m = oo, 238 | tag = "ckks_bootstrap_65536_classic_128" 239 | ) 240 | 241 | ckks_bootstrap_131072_classic_192 = LWE.Parameters( 242 | n = 131072, 243 | q = 2**2425, 244 | Xs = ND.UniformMod(3), 245 | Xe = ND.DiscreteGaussian(3.19), 246 | m = oo, 247 | tag = "ckks_bootstrap_131072_classic_128" 248 | ) 249 | 250 | Table_5_7 = [ 251 | (ckks_bootstrap_65536_classic_128_1, 128, classic_model), 252 | (ckks_bootstrap_65536_classic_128_2, 128, classic_model), 253 | (ckks_bootstrap_131072_classic_192, 192, classic_model), 254 | ] 255 | 256 | Tables = Table_5_4 + Table_5_5 + Table_5_6 + Table_5_7 257 | 258 | def run(): 259 | 260 | from functools import partial 261 | from estimator.lwe_dual import dual_hybrid 262 | dh = partial(dual_hybrid) 263 | 264 | for x in Tables: 265 | print("Testing parameter set: {}".format(x[0].tag)) 266 | print("Target level: {}".format(x[1])) 267 | print("uSVP estimate:") 268 | usvp = LWE.primal_usvp(x[0], red_cost_model = x[2]) 269 | print(usvp) 270 | print("Hybrid dual estimate:") 271 | dual = dh(x[0], red_cost_model = x[2]) 272 | print(dual) 273 | print(" ") 274 | print("------------------------------------------------") 275 | print(" ") 276 | return 0 277 | 278 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/openfhe/FHE_table.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================== 2 | // BSD 2-Clause License 3 | // 4 | // Copyright (c) 2014-2022, NJIT, Duality Technologies Inc. and other contributors 5 | // 6 | // All rights reserved. 7 | // 8 | // Author TPOC: contact@openfhe.org 9 | // 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are met: 12 | // 13 | // 1. Redistributions of source code must retain the above copyright notice, this 14 | // list of conditions and the following disclaimer. 15 | // 16 | // 2. Redistributions in binary form must reproduce the above copyright notice, 17 | // this list of conditions and the following disclaimer in the documentation 18 | // and/or other materials provided with the distribution. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | //================================================================================== 31 | 32 | /* 33 | 34 | Example for CKKS bootstrapping with full packing, modified from simple-ckks-bootstrapping.cpp provided by OpenFHE library. 35 | 36 | */ 37 | 38 | #define PROFILE 39 | 40 | #include "openfhe.h" 41 | 42 | using namespace lbcrypto; 43 | 44 | void SimpleBootstrapExample(uint32_t ringDim, usint dcrtBits, usint firstMod, std::vector levelBudget, 45 | uint32_t levelsAvailableAfterBootstrap, uint32_t numDigits); 46 | double CalculateApproximationError(const std::vector>& result, 47 | const std::vector>& expectedResult) { 48 | if (result.size() != expectedResult.size()) 49 | OPENFHE_THROW(config_error, "Cannot compare vectors with different numbers of elements"); 50 | 51 | // using the average 52 | double accError = 0; 53 | for (size_t i = 0; i < result.size(); ++i) { 54 | accError += std::abs(result[i].real() - expectedResult[i].real()); 55 | } 56 | double avrg = accError / result.size(); // get the average 57 | return std::abs(std::log2(avrg)); 58 | } 59 | int main(int argc, char* argv[]) { 60 | // SetII 61 | std::cout << "--------------------RNS-CKKS with Bootstrapping Set II--------------------" << std::endl; 62 | uint32_t ringDim = 1 << 16; 63 | usint dcrtBits = 58; 64 | usint firstMod = 60; 65 | std::vector levelBudget = {3, 3}; 66 | uint32_t levelsAvailableAfterBootstrap = 5; 67 | uint32_t numDigits = 9; 68 | SimpleBootstrapExample(ringDim, dcrtBits, firstMod, levelBudget, levelsAvailableAfterBootstrap, numDigits); 69 | } 70 | 71 | void SimpleBootstrapExample(uint32_t ringDim, usint dcrtBits, usint firstMod, std::vector levelBudget, 72 | uint32_t levelsAvailableAfterBootstrap, uint32_t numDigits) { 73 | CCParams parameters; 74 | // A. Specify main parameters 75 | /* A1) Secret key distribution 76 | * The secret key distribution for CKKS should either be SPARSE_TERNARY or UNIFORM_TERNARY. 77 | * The SPARSE_TERNARY distribution was used in the original CKKS paper, 78 | * but in this example, we use UNIFORM_TERNARY because this is included in the homomorphic 79 | * encryption standard. 80 | */ 81 | SecretKeyDist secretKeyDist = UNIFORM_TERNARY; 82 | parameters.SetSecretKeyDist(secretKeyDist); 83 | 84 | /* A2) Desired security level based on FHE standards. 85 | * In this example, we use the "NotSet" option, so the example can run more quickly with 86 | * a smaller ring dimension. Note that this should be used only in 87 | * non-production environments, or by experts who understand the security 88 | * implications of their choices. In production-like environments, we recommend using 89 | * HEStd_128_classic, HEStd_192_classic, or HEStd_256_classic for 128-bit, 192-bit, 90 | * or 256-bit security, respectively. If you choose one of these as your security level, 91 | * you do not need to set the ring dimension. 92 | */ 93 | parameters.SetSecurityLevel(HEStd_128_classic); 94 | parameters.SetRingDim(ringDim); 95 | 96 | /* A3) Scaling parameters. 97 | * By default, we set the modulus sizes and rescaling technique to the following values 98 | * to obtain a good precision and performance tradeoff. We recommend keeping the parameters 99 | * below unless you are an FHE expert. 100 | */ 101 | ScalingTechnique rescaleTech = FLEXIBLEAUTO; 102 | // usint dcrtBits = 58; 103 | // usint firstMod = 60; 104 | 105 | parameters.SetScalingModSize(dcrtBits); 106 | parameters.SetScalingTechnique(rescaleTech); 107 | parameters.SetFirstModSize(firstMod); 108 | 109 | parameters.SetNumLargeDigits(numDigits); 110 | parameters.SetKeySwitchTechnique(HYBRID); 111 | 112 | /* A4) Multiplicative depth. 113 | * The goal of bootstrapping is to increase the number of available levels we have, or in other words, 114 | * to dynamically increase the multiplicative depth. However, the bootstrapping procedure itself 115 | * needs to consume a few levels to run. We compute the number of bootstrapping levels required 116 | * using GetBootstrapDepth, and add it to levelsAvailableAfterBootstrap to set our initial multiplicative 117 | * depth. We recommend using the input parameters below to get started. 118 | */ 119 | 120 | usint depth = levelsAvailableAfterBootstrap + FHECKKSRNS::GetBootstrapDepth(levelBudget, secretKeyDist); 121 | std::cout << "Level consumption for SlotsToCoeffs: " << levelBudget[0] << std::endl; 122 | std::cout << "Level consumption for EvalMod: " 123 | << depth - levelsAvailableAfterBootstrap - levelBudget[0] - levelBudget[1] - 1 << std::endl; 124 | std::cout << "Level consumption for CoeffsToSlots: " << levelBudget[1] << std::endl; 125 | parameters.SetMultiplicativeDepth(depth); 126 | std::cout << "depth = " << depth << std::endl; 127 | CryptoContext cryptoContext = GenCryptoContext(parameters); 128 | 129 | cryptoContext->Enable(PKE); 130 | cryptoContext->Enable(KEYSWITCH); 131 | cryptoContext->Enable(LEVELEDSHE); 132 | cryptoContext->Enable(ADVANCEDSHE); 133 | cryptoContext->Enable(FHE); 134 | 135 | // This is the maximum number of slots that can be used for full packing. 136 | usint numSlots = ringDim / 2; 137 | std::cout << "CKKS scheme is using ring dimension " << ringDim << std::endl; 138 | std::cout << "# of slots = " << numSlots << std::endl << std::endl; 139 | 140 | std::cout << "CKKS scheme is using ring dimension " << ringDim << std::endl << std::endl; 141 | std::cout << "log Q " << cryptoContext->GetModulus().GetMSB() << std::endl << std::endl; 142 | const auto cryptoParamsCKKS = 143 | std::dynamic_pointer_cast(cryptoContext->GetCryptoParameters()); 144 | std::cout << "log P " << cryptoParamsCKKS->GetParamsP()->GetModulus().GetMSB() << std::endl << std::endl; 145 | std::cout << "log PQ " << cryptoParamsCKKS->GetParamsQP()->GetModulus().GetMSB() << std::endl << std::endl; 146 | 147 | cryptoContext->EvalBootstrapSetup(levelBudget); 148 | 149 | auto keyPair = cryptoContext->KeyGen(); 150 | cryptoContext->EvalMultKeyGen(keyPair.secretKey); 151 | cryptoContext->EvalBootstrapKeyGen(keyPair.secretKey, numSlots); 152 | 153 | std::vector x; 154 | std::random_device rd; 155 | std::mt19937 gen(rd()); 156 | std::uniform_real_distribution<> dis(-1.0, 1.0); 157 | for (size_t i = 0; i < numSlots; i++) { 158 | x.push_back(dis(gen)); 159 | } 160 | 161 | size_t encodedLength = x.size(); 162 | 163 | Plaintext ptxt = cryptoContext->MakeCKKSPackedPlaintext(x, 1, depth - 1); 164 | 165 | ptxt->SetLength(encodedLength); 166 | 167 | Ciphertext ciph = cryptoContext->Encrypt(keyPair.publicKey, ptxt); 168 | 169 | std::cout << "Initial number of levels remaining: " << depth - ciph->GetLevel() << std::endl; 170 | 171 | // Perform the bootstrapping operation. The goal is to increase the number of levels remaining 172 | // for HE computation. 173 | auto ciphertextAfter = cryptoContext->EvalBootstrap(ciph); 174 | 175 | std::cout << "Number of levels remaining after bootstrapping: " << depth - ciphertextAfter->GetLevel() << std::endl 176 | << std::endl; 177 | 178 | Plaintext result; 179 | cryptoContext->Decrypt(keyPair.secretKey, ciphertextAfter, &result); 180 | result->SetLength(encodedLength); 181 | // std::cout << "Output after bootstrapping \n\t" << result << std::endl; 182 | auto actualResult = result->GetCKKSPackedValue(); 183 | double precision = CalculateApproximationError(actualResult, ptxt->GetCKKSPackedValue()); 184 | std::cout << "Real precision in bits: " << precision << std::endl; 185 | } 186 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/templates/bootstrapping/main.go: -------------------------------------------------------------------------------- 1 | // Package main implements an example showcasing the basics of the bootstrapping for fixed-point approximate arithmetic over the reals/complexes. 2 | // The bootstrapping is a circuit that homomorphically re-encrypts a ciphertext at level zero to a ciphertext at a higher level, enabling further computations. 3 | // Note that, unlike other bootstrappings (BGV/BFV/TFHE), the this bootstrapping does not reduce the error in the ciphertext, but only enables further computations. 4 | // This example shows how to bootstrap a single ciphertext whose ring degree is the same as the one of the bootstrapping parameters. 5 | // Use the flag -short to run the examples fast but with insecure parameters. 6 | // 7 | // This example requires 24GB of memory to run with 128-bit secure parameters (LogN=16). 8 | package main 9 | 10 | import ( 11 | "flag" 12 | "fmt" 13 | "math" 14 | "time" 15 | 16 | "FHE-Security-Guidelines/RNS-CKKS-examples/lattigo/parameters" 17 | "FHE-Security-Guidelines/RNS-CKKS-examples/lattigo/templates/bootstrapping/failure" 18 | 19 | "github.com/tuneinsight/lattigo/v5/core/rlwe" 20 | "github.com/tuneinsight/lattigo/v5/he/hefloat" 21 | "github.com/tuneinsight/lattigo/v5/he/hefloat/bootstrapping" 22 | "github.com/tuneinsight/lattigo/v5/ring" 23 | "github.com/tuneinsight/lattigo/v5/utils" 24 | ) 25 | 26 | var flagShort = flag.Bool("short", false, "run the example with a smaller and insecure ring degree.") 27 | 28 | type Parameters struct { 29 | ResidualLit hefloat.ParametersLiteral 30 | BootstrappingLit bootstrapping.ParametersLiteral 31 | } 32 | 33 | var ParametersClassical = map[int]Parameters{ 34 | 128: { 35 | 36 | // First we must define the residual parameters. 37 | // The residual parameters are the parameters used outside of the bootstrapping circuit. 38 | ResidualLit: hefloat.ParametersLiteral{ 39 | LogN: 16, // Log2 of the ring degree 40 | LogQ: []int{45, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}, // Log2 of the ciphertext prime moduli 41 | LogP: []int{55, 40, 40}, // Log2 of the key-switch auxiliary prime moduli 42 | LogDefaultScale: 35, // Log2 of the scale 43 | }, 44 | 45 | // The bootstrapping circuit use its own Parameters 46 | // which will be automatically instantiated given 47 | // the residual parameters and the bootstrapping parameters. 48 | 49 | // !WARNING! The bootstrapping parameters are not ensured to 50 | // be 128-bit secure, it is the responsibility of the user 51 | // to check that the meet the security requirement and tweak 52 | // them if necessary. 53 | 54 | // In this example we need to specify multiple advanced parameters 55 | // for the bootstrapping to work since we are constrainted to use 56 | // a secret with density 2/3. 57 | BootstrappingLit: bootstrapping.ParametersLiteral{ 58 | // We specify LogN to ensure that both the residual 59 | // parameters and the bootstrapping parameters have 60 | // the same LogN. This is not required, but we want 61 | // it for this example. 62 | LogN: utils.Pointy(16), 63 | 64 | // In this example we manually specify the 65 | // bootstrapping parameters' secret distribution. 66 | // This is not necessary, but we ensure here that 67 | // they are the same as the residual parameters. 68 | Xs: ring.Ternary{P: 2 / 3.0}, 69 | 70 | // By default the Sparse-Secret Encapsulation technique of 71 | // https://eprint.iacr.org/2022/024 is used, so we manually 72 | // set it to 0 to not use it. 73 | EphemeralSecretWeight: utils.Pointy(0), 74 | 75 | // The default values for the following fields is set for 76 | // an expected precision of ~27.5 bits, however since we are 77 | // constrained to a dense secrete, the final precision is closer 78 | // to ~16 bits, so the size of the prime moduli can be reduced 79 | // to gain some more homomorphic capacity to allocate to the 80 | // residual parameters. 81 | SlotsToCoeffsFactorizationDepthAndLogScales: [][]int{{30}, {30}, {30}}, 82 | 83 | K: utils.Pointy(512), 84 | // We then need adapt the approximation of the homomorphic 85 | // modular reduction accordingly. 86 | Mod1Type: hefloat.CosContinuous, 87 | Mod1Degree: utils.Pointy(255), 88 | DoubleAngle: utils.Pointy(4), 89 | }, 90 | }, 91 | } 92 | 93 | func main() { 94 | 95 | flag.Parse() 96 | 97 | ResidualLit := ParametersClassical[128].ResidualLit 98 | BootstrappingLit := ParametersClassical[128].BootstrappingLit 99 | 100 | if *flagShort { 101 | ResidualLit.LogN -= 2 102 | BootstrappingLit.LogN = utils.Pointy(ResidualLit.LogN) 103 | } 104 | 105 | //============================== 106 | //=== 1) RESIDUAL PARAMETERS === 107 | //============================== 108 | 109 | params, err := hefloat.NewParametersFromLiteral(ResidualLit) 110 | 111 | if err != nil { 112 | panic(err) 113 | } 114 | 115 | //========================================== 116 | //=== 2) BOOTSTRAPPING PARAMETERSLITERAL === 117 | //========================================== 118 | 119 | // We can estimate the bootstrapping failure probability with: 120 | fmt.Println("==== FAILURE PROBABILITY ====") 121 | Xs := params.Xs().(ring.Ternary) 122 | pr := failure.Probability(&Xs, *BootstrappingLit.K, params.LogN(), params.LogMaxSlots()) 123 | fmt.Printf("Failure Probability given K=%d: 2^{%f}\n", *BootstrappingLit.K, pr) 124 | fmt.Println("=============================") 125 | 126 | //=================================== 127 | //=== 3) BOOTSTRAPPING PARAMETERS === 128 | //=================================== 129 | 130 | // Now that the residual parameters and the bootstrapping parameters 131 | // literals are defined, we can instantiate the bootstrapping parameters. 132 | // The instantiated bootstrapping parameters store their own hefloat.Parameter, 133 | // which are the parameters of the ring used by the bootstrapping circuit. 134 | // The bootstrapping parameters are a wrapper of hefloat.Parameters, 135 | // with additional information. 136 | // They therefore has the same API as the hefloat.Parameters 137 | // and we can use this API to print some information. 138 | btpParams, err := bootstrapping.NewParametersFromLiteral(params, BootstrappingLit) 139 | if err != nil { 140 | panic(err) 141 | } 142 | 143 | if *flagShort { 144 | // Corrects the message ratio Q0/|m(X)| to take into account the 145 | // smaller number of slots and keep the same precision 146 | btpParams.Mod1ParametersLiteral.LogMessageRatio += 16 - params.LogN() 147 | } 148 | 149 | // Logs information about the residual parameters 150 | fmt.Printf("\nResidual Parameters\n%s\n\n", parameters.Infos(params)) 151 | 152 | // Checks that the residual parameters are compliant with 128-bit classical security 153 | if err = parameters.AssertSecurity(params, 128, parameters.Classical); err != nil { 154 | if *flagShort { 155 | fmt.Printf("warning: %s\n\n", err) 156 | } else { 157 | panic(err) 158 | } 159 | } 160 | 161 | // Logs information about the bootstrapping parameters 162 | fmt.Printf("\n Bootstrapping Parameters\n%s\n\n", parameters.Infos(btpParams.BootstrappingParameters)) 163 | 164 | // Checks that the bootstrapping parameters are compliant with 128-bit classical security 165 | if err = parameters.AssertSecurity(btpParams.BootstrappingParameters, 128, parameters.Classical); err != nil { 166 | if *flagShort { 167 | fmt.Printf("warning: %s\n\n", err) 168 | } else { 169 | panic(err) 170 | } 171 | } // 172 | 173 | //============================== 174 | //=== 4) KEYGEN & ENCRYPTION === 175 | //============================== 176 | 177 | // Now that both the residual and bootstrapping parameters are instantiated, we can 178 | // instantiate the usual necessary object to encode, encrypt and decrypt. 179 | 180 | // Scheme context and keys 181 | kgen := rlwe.NewKeyGenerator(params) 182 | 183 | sk, pk := kgen.GenKeyPairNew() 184 | 185 | encoder := hefloat.NewEncoder(params) 186 | decryptor := rlwe.NewDecryptor(params, sk) 187 | encryptor := rlwe.NewEncryptor(params, pk) 188 | 189 | fmt.Println() 190 | fmt.Println("Generating bootstrapping evaluation keys...") 191 | evk, _, err := btpParams.GenEvaluationKeys(sk) 192 | if err != nil { 193 | panic(err) 194 | } 195 | fmt.Println("Done") 196 | 197 | //======================== 198 | //=== 5) BOOTSTRAPPING === 199 | //======================== 200 | 201 | // Instantiates the bootstrapper 202 | var eval *bootstrapping.Evaluator 203 | if eval, err = bootstrapping.NewEvaluator(btpParams, evk); err != nil { 204 | panic(err) 205 | } 206 | 207 | // Generate a random plaintext with values uniformely distributed 208 | // in [-1, 1] for the real and imaginary part. 209 | slots := params.MaxSlots() 210 | valuesWant := make([]complex128, params.MaxSlots()) 211 | for i := range valuesWant { 212 | valuesWant[i] = complex(float64(i)/float64(slots-1), float64(i)/float64(slots-1)) 213 | } 214 | 215 | // We encrypt at level 0 216 | plaintext := hefloat.NewPlaintext(params, 0) 217 | if err := encoder.Encode(valuesWant, plaintext); err != nil { 218 | panic(err) 219 | } 220 | 221 | // Encrypt 222 | ciphertext1, err := encryptor.EncryptNew(plaintext) 223 | if err != nil { 224 | panic(err) 225 | } 226 | 227 | // Decrypt, print and compare with the plaintext values 228 | fmt.Println() 229 | fmt.Println("Precision of values vs. ciphertext") 230 | valuesTest1 := printDebug(params, ciphertext1, valuesWant, decryptor, encoder) 231 | 232 | // Bootstrap the ciphertext (homomorphic re-encryption) 233 | // It takes a ciphertext at level 0 (if not at level 0, then it will reduce it to level 0) 234 | // and returns a ciphertext with the max level of `floatParamsResidualLit`. 235 | // CAUTION: the scale of the ciphertext MUST be equal (or very close) to params.DefaultScale() 236 | // To equalize the scale, the function evaluator.SetScale(ciphertext, parameters.DefaultScale()) can be used at the expense of one level. 237 | // If the ciphertext is is at level one or greater when given to the bootstrapper, this equalization is automatically done. 238 | fmt.Println("Bootstrapping...") 239 | now := time.Now() 240 | ciphertext2, err := eval.Bootstrap(ciphertext1) 241 | if err != nil { 242 | panic(err) 243 | } 244 | fmt.Printf("Done: %s\n", time.Since(now)) 245 | 246 | //===================== 247 | //=== 6) DECRYPTION === 248 | //===================== 249 | 250 | // Decrypt, print and compare with the plaintext values 251 | fmt.Println() 252 | fmt.Println("Precision of ciphertext vs. Bootstrap(ciphertext)") 253 | printDebug(params, ciphertext2, valuesTest1, decryptor, encoder) 254 | } 255 | 256 | func printDebug(params hefloat.Parameters, ciphertext *rlwe.Ciphertext, valuesWant []complex128, decryptor *rlwe.Decryptor, encoder *hefloat.Encoder) (valuesTest []complex128) { 257 | 258 | valuesTest = make([]complex128, ciphertext.Slots()) 259 | 260 | if err := encoder.Decode(decryptor.DecryptNew(ciphertext), valuesTest); err != nil { 261 | panic(err) 262 | } 263 | 264 | fmt.Println() 265 | fmt.Printf("Level: %d (logQ = %d)\n", ciphertext.Level(), params.LogQLvl(ciphertext.Level())) 266 | 267 | fmt.Printf("Scale: 2^%f\n", math.Log2(ciphertext.Scale.Float64())) 268 | fmt.Printf("ValuesTest: %6.10f %6.10f %6.10f %6.10f...\n", valuesTest[0], valuesTest[1], valuesTest[2], valuesTest[3]) 269 | fmt.Printf("ValuesWant: %6.10f %6.10f %6.10f %6.10f...\n", valuesWant[0], valuesWant[1], valuesWant[2], valuesWant[3]) 270 | 271 | precStats := hefloat.GetPrecisionStats(params, encoder, nil, valuesWant, valuesTest, 0, false) 272 | 273 | fmt.Println(precStats.String()) 274 | fmt.Println() 275 | 276 | return 277 | } 278 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/openfhe/SHE_table.cpp: -------------------------------------------------------------------------------- 1 | //================================================================================== 2 | // BSD 2-Clause License 3 | // 4 | // Copyright (c) 2014-2022, NJIT, Duality Technologies Inc. and other contributors 5 | // 6 | // All rights reserved. 7 | // 8 | // Author TPOC: contact@openfhe.org 9 | // 10 | // Redistribution and use in source and binary forms, with or without 11 | // modification, are permitted provided that the following conditions are met: 12 | // 13 | // 1. Redistributions of source code must retain the above copyright notice, this 14 | // list of conditions and the following disclaimer. 15 | // 16 | // 2. Redistributions in binary form must reproduce the above copyright notice, 17 | // this list of conditions and the following disclaimer in the documentation 18 | // and/or other materials provided with the distribution. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | //================================================================================== 31 | 32 | /* 33 | Simple examples for CKKS without Bootstrapping, modified from simple-real-numbers.cpp provided by OpenFHE. 34 | */ 35 | 36 | #define PROFILE 37 | 38 | #include "openfhe.h" 39 | 40 | using namespace lbcrypto; 41 | void SHEExample(uint32_t ringDim, usint dcrtBits, usint firstMod, usint depth, SecurityLevel secLevel); 42 | 43 | // CalculateApproximationError() calculates the precision number (or approximation error). 44 | // The higher the precision, the less the error. 45 | double CalculateApproximationError(const std::vector>& result, 46 | const std::vector>& expectedResult) { 47 | if (result.size() != expectedResult.size()) 48 | OPENFHE_THROW(config_error, "Cannot compare vectors with different numbers of elements"); 49 | 50 | // using the average 51 | double accError = 0; 52 | for (size_t i = 0; i < result.size(); ++i) { 53 | accError += std::abs(result[i].real() - expectedResult[i].real()); 54 | } 55 | double avrg = accError / result.size(); // get the average 56 | return std::abs(std::log2(avrg)); 57 | } 58 | 59 | int main(int argc, char* argv[]) { 60 | // SetII 61 | std::cout << "====================RNS-CKKS without Bootstrapping====================" << std::endl; 62 | std::cout << "--------------------COLUMN 1--------------------" << std::endl; 63 | uint32_t ringDim = 1 << 14; 64 | usint dcrtBits = 38; 65 | usint firstMod = 40; 66 | usint depth = 7; 67 | SHEExample(ringDim, dcrtBits, firstMod, depth, HEStd_128_classic); 68 | 69 | std::cout << "--------------------COLUMN 2--------------------" << std::endl; 70 | ringDim = 1 << 15; 71 | dcrtBits = 41; 72 | firstMod = 43; 73 | depth = 9; 74 | SHEExample(ringDim, dcrtBits, firstMod, depth, HEStd_192_classic); 75 | 76 | std::cout << "--------------------COLUMN 3--------------------" << std::endl; 77 | ringDim = 1 << 15; 78 | dcrtBits = 39; 79 | firstMod = 40; 80 | depth = 7; 81 | SHEExample(ringDim, dcrtBits, firstMod, depth, HEStd_256_classic); 82 | 83 | } 84 | void SHEExample(uint32_t ringDim, usint dcrtBits, usint firstMod, usint depth, SecurityLevel secLevel) { 85 | // Step 1: Setup CryptoContext 86 | 87 | // A. Specify main parameters 88 | CCParams parameters; 89 | /* A1) Secret key distribution 90 | * The secret key distribution for CKKS should either be SPARSE_TERNARY or UNIFORM_TERNARY. 91 | * The SPARSE_TERNARY distribution was used in the original CKKS paper, 92 | * but in this example, we use UNIFORM_TERNARY because this is included in the homomorphic 93 | * encryption standard. 94 | */ 95 | SecretKeyDist secretKeyDist = UNIFORM_TERNARY; 96 | parameters.SetSecretKeyDist(secretKeyDist); 97 | 98 | parameters.SetSecurityLevel(secLevel); 99 | parameters.SetRingDim(ringDim); 100 | 101 | /* A2) Bit-length of scaling factor. 102 | * CKKS works for real numbers, but these numbers are encoded as integers. 103 | * For instance, real number m=0.01 is encoded as m'=round(m*D), where D is 104 | * a scheme parameter called scaling factor. Suppose D=1000, then m' is 10 (an 105 | * integer). Say the result of a computation based on m' is 130, then at 106 | * decryption, the scaling factor is removed so the user is presented with 107 | * the real number result of 0.13. 108 | * 109 | * Parameter 'scaleModSize' determines the bit-length of the scaling 110 | * factor D, but not the scaling factor itself. The latter is implementation 111 | * specific, and it may also vary between ciphertexts in certain versions of 112 | * CKKS (e.g., in FLEXIBLEAUTO). 113 | * 114 | * Choosing 'scaleModSize' depends on the desired accuracy of the 115 | * computation, as well as the remaining parameters like multDepth or security 116 | * standard. This is because the remaining parameters determine how much noise 117 | * will be incurred during the computation (remember CKKS is an approximate 118 | * scheme that incurs small amounts of noise with every operation). The 119 | * scaling factor should be large enough to both accommodate this noise and 120 | * support results that match the desired accuracy. 121 | */ 122 | 123 | ScalingTechnique rescaleTech = FLEXIBLEAUTO; 124 | 125 | /* A4) Desired security level based on FHE standards. 126 | * This parameter can take four values. Three of the possible values 127 | * correspond to 128-bit, 192-bit, and 256-bit security, and the fourth value 128 | * corresponds to "NotSet", which means that the user is responsible for 129 | * choosing security parameters. Naturally, "NotSet" should be used only in 130 | * non-production environments, or by experts who understand the security 131 | * implications of their choices. 132 | * 133 | * If a given security level is selected, the library will consult the current 134 | * security parameter tables defined by the FHE standards consortium 135 | * (https://homomorphicencryption.org/introduction/) to automatically 136 | * select the security parameters. Please see "TABLES of RECOMMENDED 137 | * PARAMETERS" in the following reference for more details: 138 | * http://homomorphicencryption.org/wp-content/uploads/2018/11/HomomorphicEncryptionStandardv1.1.pdf 139 | */ 140 | parameters.SetScalingModSize(dcrtBits); 141 | parameters.SetScalingTechnique(rescaleTech); 142 | parameters.SetFirstModSize(firstMod); 143 | 144 | parameters.SetMultiplicativeDepth(depth); 145 | 146 | CryptoContext cc = GenCryptoContext(parameters); 147 | // Enable the features that you wish to use 148 | cc->Enable(PKE); 149 | cc->Enable(KEYSWITCH); 150 | cc->Enable(LEVELEDSHE); 151 | cc->Enable(ADVANCEDSHE); 152 | cc->Enable(FHE); 153 | /*A3) Number of plaintext slots used in the ciphertext. 154 | * CKKS packs multiple plaintext values in each ciphertext. 155 | * The maximum number of slots depends on a security parameter called ring 156 | * dimension. */ 157 | /* 158 | * Please use method GetRingDimension() to find out the exact ring dimension 159 | * being used for these parameters. Give ring dimension N, the maximum batch 160 | * size is N/2, because of the way CKKS works. 161 | */ 162 | // usint ringDim = cc->GetRingDimension(); 163 | std::cout << "CKKS scheme is using ring dimension " << ringDim << std::endl << std::endl; 164 | std::cout << "log Q " << cc->GetModulus().GetMSB() << std::endl << std::endl; 165 | const auto cryptoParamsCKKS = std::dynamic_pointer_cast(cc->GetCryptoParameters()); 166 | std::cout << "log P " << cryptoParamsCKKS->GetParamsP()->GetModulus().GetMSB() << std::endl << std::endl; 167 | std::cout << "log PQ " << cryptoParamsCKKS->GetParamsQP()->GetModulus().GetMSB() << std::endl << std::endl; 168 | 169 | uint32_t batchSize = ringDim / 2; 170 | // uint32_t batchSize = 8; 171 | // B. Step 2: Key Generation 172 | /* B1) Generate encryption keys. 173 | * These are used for encryption/decryption, as well as in generating 174 | * different kinds of keys. 175 | */ 176 | auto keys = cc->KeyGen(); 177 | 178 | /* B2) Generate the digit size 179 | * In CKKS, whenever someone multiplies two ciphertexts encrypted with key s, 180 | * we get a result with some components that are valid under key s, and 181 | * with an additional component that's valid under key s^2. 182 | * 183 | * In most cases, we want to perform relinearization of the multiplicaiton 184 | * result, i.e., we want to transform the s^2 component of the ciphertext so 185 | * it becomes valid under original key s. To do so, we need to create what we 186 | * call a relinearization key with the following line. 187 | */ 188 | cc->EvalMultKeyGen(keys.secretKey); 189 | 190 | /* B3) Generate the rotation keys 191 | * CKKS supports rotating the contents of a packed ciphertext, but to do so, 192 | * we need to create what we call a rotation key. This is done with the 193 | * following call, which takes as input a vector with indices that correspond 194 | * to the rotation offset we want to support. Negative indices correspond to 195 | * right shift and positive to left shift. Look at the output of this demo for 196 | * an illustration of this. 197 | * 198 | * Keep in mind that rotations work over the batch size or entire ring dimension (if the batch size is not specified). 199 | * This means that, if ring dimension is 8 and batch 200 | * size is not specified, then an input (1,2,3,4,0,0,0,0) rotated by 2 will become 201 | * (3,4,0,0,0,0,1,2) and not (3,4,1,2,0,0,0,0). 202 | * If ring dimension is 8 and batch 203 | * size is set to 4, then the rotation of (1,2,3,4) by 2 will become (3,4,1,2). 204 | * Also, as someone can observe 205 | * in the output of this demo, since CKKS is approximate, zeros are not exact 206 | * - they're just very small numbers. 207 | */ 208 | // cc->EvalRotateKeyGen(keys.secretKey, {1, -2}); 209 | 210 | // Step 3: Encoding and encryption of inputs 211 | 212 | // Inputs (adopted from https://github.com/microsoft/SEAL/blob/main/native/examples/5_ckks_basics.cpp) 213 | // Copyright (c) Microsoft Corporation. All rights reserved. 214 | // Licensed under the MIT license 215 | 216 | std::vector x1; 217 | std::random_device rd; 218 | std::mt19937 gen(rd()); 219 | std::uniform_real_distribution<> dis(-1.0, 1.0); 220 | for (size_t i = 0; i < batchSize; i++) { 221 | x1.push_back(dis(gen)); 222 | } 223 | 224 | // Encoding as plaintexts 225 | Plaintext ptxt1 = cc->MakeCKKSPackedPlaintext(x1); 226 | // std::cout << "Input x1: " << ptxt1 << std::endl; 227 | 228 | // Encrypt the encoded vectors 229 | auto c1 = cc->Encrypt(keys.publicKey, ptxt1); 230 | auto c0 = cc->Encrypt(keys.publicKey, ptxt1); 231 | // Step 4: Evaluation 232 | 233 | // Homomorphic multiplication 234 | // std::cout<<"c1 level=" << c1->GetLevel() << std::endl; 235 | 236 | for (uint32_t i = 0; i < depth; i++) { 237 | // c1 = cc->EvalMult(c1, c1);//square f(x)*f(x) 238 | // std::cout<<"co"<EvalMult(c1, c0); // mul: f(x)*x 240 | } 241 | std::cout << "# of multiplications = " << depth << std::endl; 242 | std::vector expectedResult; 243 | // std::cout << "cleartext results = "; 244 | for (double entry : x1) { 245 | double expectedEntry = std::pow(entry, depth + 1); // mul: f(x)*x 246 | // double expectedEntry = std::pow(entry, std::pow(2, depth)); //square f(x)*f(x) 247 | expectedResult.push_back(expectedEntry); 248 | 249 | // std::cout << expectedEntry << ' '; 250 | } 251 | 252 | std::cout << std::endl; 253 | Plaintext ptxt_expResult = cc->MakeCKKSPackedPlaintext(expectedResult); 254 | 255 | // Step 5: Decryption and output 256 | Plaintext result; 257 | // We set the cout precision to 8 decimal digits for a nicer output. 258 | // If you want to see the error/noise introduced by CKKS, bump it up 259 | // to 15 and it should become visible. 260 | std::cout.precision(50); 261 | 262 | std::cout << std::endl << "Results of homomorphic computations: " << std::endl; 263 | cc->Decrypt(keys.secretKey, c1, &result); 264 | result->SetLength(batchSize); 265 | 266 | std::cout << "Estimated precision in bits: " << result->GetLogPrecision() << std::endl; 267 | auto actualResult = result->GetCKKSPackedValue(); 268 | // std::cout << "Actual results = " << actualResult << std::endl; 269 | double precision = CalculateApproximationError(actualResult, ptxt_expResult->GetCKKSPackedValue()); 270 | std::cout << "Real precision in bits: " << precision << std::endl; 271 | } 272 | -------------------------------------------------------------------------------- /max_logQ_tables.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | sys.path.insert(1, 'lattice-estimator') 4 | 5 | from estimator import * 6 | from functools import partial 7 | from sage.all import oo, log 8 | import time 9 | 10 | MODE_TERNARY = ND.Uniform(-1, 1) 11 | MODE_GAUSSIAN = ND.DiscreteGaussian(stddev=3.19, mean=0, n=None) 12 | #NOTE: sparse-LWE is currently not recommended in the guideline 2/16/2024 13 | 14 | error_dist = ND.DiscreteGaussian(stddev=3.19, mean=0, n=None) 15 | # error_dist = ND.CenteredBinomial(21) central binormial distribution with 42 coins, std = 3.24 16 | secret_mode = MODE_TERNARY # MODE_TERNARY or MODE_GAUSSIAN 17 | cost_model_classical = RC.MATZOV 18 | cost_model_quantum = RC.ChaLoy21#RC.LaaMosPol14 19 | m = oo 20 | n_list = [2**i for i in range(10, 18)] 21 | 22 | # def initial_log_q(n, secret_dist, security_thres, power_setting): 23 | # # Use linear function to compute inital_log_q = slope*dimension + intercept 24 | # # Format: (slope, intercept) 25 | # coefficients = { 26 | # (128, MODE_TERNARY, "classical"): (0.02730, -7.09195), 27 | # (128, MODE_GAUSSIAN, "classical"): (0.02732, -13.93678), 28 | # (192, MODE_TERNARY, "classical"): (0.01885, -3.87931), 29 | # (192, MODE_GAUSSIAN, "classical"): (0.01885, -1.87931), 30 | # (256, MODE_TERNARY, "classical"): (0.01465, -3.08046), 31 | # (256, MODE_GAUSSIAN, "classical"): (0.01368, 15.95402), 32 | # (128, MODE_TERNARY, "quantum"): (0.02555, 2.08621), 33 | # (128, MODE_GAUSSIAN, "quantum"): (0.02557, -4.51724), 34 | # (192, MODE_TERNARY, "quantum"): (0.01757, -3.32184), 35 | # (192, MODE_GAUSSIAN, "quantum"): (0.01757, -1.32184), 36 | # (256, MODE_TERNARY, "quantum"): (0.01459, -19.25287), 37 | # (256, MODE_GAUSSIAN, "quantum"): (0.01362, -0.44253), 38 | # } 39 | 40 | # # Get the appropriate coefficients based on the inputs 41 | # key = (security_thres, secret_dist, power_setting) 42 | # if key in coefficients: 43 | # a, b = coefficients[key] 44 | # log_q = a * n + b 45 | # return round(log_q) 46 | # else: 47 | # return "Invalid input combination. Please check your inputs and try again." 48 | 49 | def initial_log_q(n_dim, secret_dist, security_thres, power_setting): 50 | # Look-up table to retrieve the initial_log_q 51 | if n_dim < 1000 or n_dim > 2**17: 52 | return "Error: Only dimensions between 1000 and 2^17 (131072) are supported." 53 | 54 | # Define n_list 55 | n_list = [2**i for i in range(17, 9, -1)] 56 | 57 | # Lookup tables for classical settings 58 | logq_initial_classic_ternary = { 59 | 128: {n_s: logq for n_s, logq in zip(n_list, [3523, 1747, 868, 431, 214, 107, 53, 26])}, 60 | 192: {n_s: logq for n_s, logq in zip(n_list, [2411, 1199, 597, 297, 148, 73, 36, 36])}, #dummy entry at the end 61 | 256: {n_s: logq for n_s, logq in zip(n_list, [1866, 929, 463, 230, 114, 56, 27, 27])} #dummy entry at the end 62 | } 63 | 64 | logq_initial_classic_Gaussian = { 65 | 128: {n_s: logq for n_s, logq in zip(n_list, [3525, 1749, 870, 433, 216, 109, 55, 29])}, 66 | 192: {n_s: logq for n_s, logq in zip(n_list, [2413, 1201, 599, 299, 150, 75, 38, 38])},#dummy entry at the end 67 | 256: {n_s: logq for n_s, logq in zip(n_list, [1868, 931, 465, 232, 116, 59, 30, 30])}#dummy entry at the end 68 | } 69 | 70 | # Lookup tables for quantum settings 71 | logq_initial_quantum_ternary = { 72 | 128: {n_s: logq for n_s, logq in zip(n_list, [3348, 1663, 825, 409, 203, 101, 50, 25])}, 73 | 192: {n_s: logq for n_s, logq in zip(n_list, [2301, 1145, 570, 283, 140, 69, 34, 34])},#dummy entry at the end 74 | 256: {n_s: logq for n_s, logq in zip(n_list, [1784, 888, 442, 219, 108, 53, 26, 26])}#dummy entry at the end 75 | } 76 | 77 | logq_initial_quantum_Gaussian = { 78 | 128: {n_s: logq for n_s, logq in zip(n_list, [3351, 1665, 827, 411, 205, 103, 52, 27])}, 79 | 192: {n_s: logq for n_s, logq in zip(n_list, [2304, 1147, 572, 285, 143, 72, 36, 36])},#dummy entry at the end 80 | 256: {n_s: logq for n_s, logq in zip(n_list, [1786, 890, 445, 222, 111, 56, 28, 28])}#dummy entry at the end 81 | } 82 | 83 | # Select the appropriate lookup table based on power_setting and secret_dist 84 | if power_setting == "classical" and secret_dist == MODE_TERNARY: 85 | lookup_table = logq_initial_classic_ternary 86 | elif power_setting == "classical" and secret_dist == MODE_GAUSSIAN: 87 | lookup_table = logq_initial_classic_Gaussian 88 | elif power_setting == "quantum" and secret_dist == MODE_TERNARY: 89 | lookup_table = logq_initial_quantum_ternary 90 | elif power_setting == "quantum" and secret_dist == MODE_GAUSSIAN: 91 | lookup_table = logq_initial_quantum_Gaussian 92 | else: 93 | return "Invalid input combination. Please check your inputs and try again." 94 | 95 | # Get the appropriate log_q value 96 | try: 97 | log_q = lookup_table[security_thres][n_dim] 98 | # print(n_dim, log_q) 99 | return log_q 100 | except KeyError: 101 | return "Invalid input combination. Please check your inputs and try again." 102 | 103 | ESTIMATORS = { 104 | "classical": { 105 | MODE_TERNARY: [ 106 | partial(LWE.primal_usvp, red_cost_model=cost_model_classical), 107 | partial(LWE.dual_hybrid, red_cost_model=cost_model_classical) 108 | ,partial(LWE.primal_hybrid, mitm=False, babai=False, red_cost_model=cost_model_classical) 109 | ,partial(LWE.primal_bdd, red_cost_model=cost_model_classical) 110 | ], 111 | MODE_GAUSSIAN: [ 112 | partial(LWE.primal_usvp, red_cost_model=cost_model_classical), 113 | partial(LWE.dual_hybrid, red_cost_model=cost_model_classical) 114 | ,partial(LWE.primal_hybrid, mitm=False, babai=False, red_cost_model=cost_model_classical) 115 | ,partial(LWE.primal_bdd, red_cost_model=cost_model_classical) 116 | ] 117 | }, 118 | "quantum": { 119 | MODE_TERNARY: [ 120 | partial(LWE.primal_usvp, red_cost_model=cost_model_quantum), 121 | partial(LWE.dual_hybrid, red_cost_model=cost_model_quantum) 122 | ,partial(LWE.primal_hybrid, mitm=False, babai=False, red_cost_model=cost_model_quantum) 123 | ,partial(LWE.primal_bdd, red_cost_model=cost_model_quantum) 124 | ], 125 | MODE_GAUSSIAN: [ 126 | partial(LWE.primal_usvp, red_cost_model=cost_model_quantum), 127 | partial(LWE.dual_hybrid, red_cost_model=cost_model_quantum) 128 | ,partial(LWE.primal_hybrid, mitm=False, babai=False, red_cost_model=cost_model_quantum) 129 | ,partial(LWE.primal_bdd, red_cost_model=cost_model_quantum) 130 | ] 131 | } 132 | } 133 | def get_estimators_for_mode(secret_mode, power_setting, n_dim): 134 | # print(secret_mode, power_setting) 135 | estimators = ESTIMATORS[power_setting][secret_mode] 136 | filtered_estimators = [] 137 | for estimator in estimators: 138 | if n_dim > 2**14 and estimator.func == LWE.primal_hybrid: 139 | continue 140 | filtered_estimators.append(estimator) 141 | return filtered_estimators 142 | 143 | def cost_estimating(estimator, logq, n_dim, secret_dist, error_dist, m = oo): 144 | try: 145 | instance = LWE.Parameters(n=n_dim, q=2**logq, Xs=secret_dist, Xe=error_dist, m=m) 146 | attack_costs = estimator(params=instance) 147 | return log(attack_costs["rop"], 2).n() 148 | 149 | except Exception as e: 150 | # Improved error handling with detailed debug information 151 | # print(f"Error during estimation: {e}") 152 | # print(f"DEBUG: logq = {logq}, n_dim = {n_dim}, secret_dist = {secret_dist}, error_dist = {error_dist}, m = {m}") 153 | # print(f"estimator: {estimator}") 154 | return None 155 | 156 | def binary_search(estimator, n_dim, secret_dist, error_dist, security_target, logq_left, logq_right): 157 | """ 158 | Output logQ such that 159 | security_estimation(2**logQ, ...) >= security_target 160 | AND 161 | security_estimation(2**(logQ + 1), ...) < security_target 162 | """ 163 | lptr, rptr = logq_left, logq_right 164 | while lptr < rptr: 165 | mid = (lptr + rptr + 1) // 2 166 | security_mid = cost_estimating(estimator, mid, n_dim, secret_dist, error_dist) 167 | if security_mid >= security_target: 168 | lptr = mid 169 | else: 170 | rptr = mid - 1 171 | assert(cost_estimating(estimator, lptr, n_dim, secret_dist, error_dist)>=security_target) 172 | assert(cost_estimating(estimator, lptr+1, n_dim, secret_dist, error_dist)= security_target 179 | security_estimation(2**logQ_right, ...) < security_target 180 | """ 181 | if n_dim < 1200: 182 | logq_interval = 5 183 | logq_left = logq_initial 184 | logq_right = None 185 | 186 | while True:#find the left bound where security just exceeds the target. 187 | security_left = cost_estimating(estimator, logq_left, n_dim, secret_mode, error_dist) 188 | if security_left >= security_target: 189 | break # Found the left bound where security meets/exceeds the target 190 | else: #logq_right is found 191 | logq_right = logq_left 192 | logq_left -= logq_interval 193 | 194 | if logq_right is None:#only when logq_left is found during the first iteration of the first while loop 195 | logq_right = logq_initial + logq_interval 196 | while True: 197 | security_right = cost_estimating(estimator, logq_right, n_dim, secret_mode, error_dist) 198 | if security_right < security_target: 199 | break 200 | else: 201 | logq_right += logq_interval 202 | # print(f"DEBUG: search range: {logq_left, logq_right}") 203 | return logq_left, logq_right 204 | 205 | def maxlogq_finder(estimator, n_dim, secret_dist, error_dist, security_target, power_setting): 206 | """Find the specific maximal logq for a given estimator and parameters.""" 207 | # print("Using estimator:", estimator) 208 | logq_initial = initial_log_q(n_dim, secret_dist, security_thres, power_setting) 209 | logq_left, logq_right = logq_search_interval(estimator, n_dim, secret_dist, error_dist, security_target, logq_initial) 210 | maxlogq = binary_search(estimator, n_dim, secret_dist, error_dist, security_target, logq_left, logq_right) 211 | return maxlogq 212 | 213 | def process_maxlogq(estimators, n_dim, secret_dist, error_dist, security_target, power_setting): 214 | logq_list = [] 215 | for est in estimators: 216 | try: 217 | logq = maxlogq_finder(est, n_dim, secret_dist, error_dist, security_target, power_setting) 218 | # print(f"DEBUG:{n_dim}, {est}") 219 | logq_list.append(logq) 220 | except Exception as e: 221 | # print(f"Error encountered with estimator {est.func.__name__} at n_dim={n_dim}: {e}") 222 | continue 223 | if not logq_list: 224 | # Handle the case where all estimators fail 225 | raise RuntimeError(f"All estimators failed for n_dim={n_dim}. Unable to compute logq.") 226 | 227 | # print(f"DEBUG: maxlogq list = {logq_list}") 228 | return min(logq_list) 229 | 230 | secret = {MODE_TERNARY: "ternary", MODE_GAUSSIAN: "Gaussian"} 231 | 232 | if __name__ == "__main__": 233 | security_thres = int(sys.argv[1]) 234 | security_margin = int(sys.argv[2]) 235 | include_quantum = sys.argv[3].lower() == "true" if len(sys.argv) > 3 else False 236 | 237 | security_target = security_thres + security_margin 238 | print(f"security threshold = {security_thres}, margin = {security_margin}, target = {security_target}") 239 | 240 | # Define headers conditionally based on whether quantum columns are included 241 | if include_quantum: 242 | headers = ["n", "Classical Ternary", "Classical Gaussian", "Quantum Ternary", "Quantum Gaussian"] 243 | else: 244 | headers = ["n", "Classical Ternary", "Classical Gaussian"] 245 | 246 | # Format headers dynamically based on the selected columns 247 | header_format = "| {:<{}s} | {:<{}s} | {:<{}s} ".format( 248 | headers[0], 8, 249 | headers[1], 17, 250 | headers[2], 18 251 | ) 252 | if include_quantum: 253 | header_format += "| {:<{}s} | {:<{}s} |".format(headers[3], 15, headers[4], 16) 254 | else: 255 | header_format += "|" 256 | 257 | separator = "+" + "-" * (10) + "+" + "-" * (19) + "+" + "-" * (20) + "+" 258 | if include_quantum: 259 | separator += "+" + "-" * (17) + "+" + "-" * (18) + "+" 260 | 261 | border = "-" * (90 if include_quantum else 53) 262 | 263 | print(border) 264 | print(header_format) 265 | print(separator) 266 | 267 | for n_dim in n_list: 268 | if n_dim < 2048 and security_target > 130: 269 | continue 270 | 271 | logq_classical_ternary = [] 272 | logq_classical_gaussian = [] 273 | logq_quantum_ternary = [] 274 | logq_quantum_gaussian = [] 275 | 276 | for power in ["classical", "quantum"] if include_quantum else ["classical"]: 277 | for secret_mode in [MODE_TERNARY, MODE_GAUSSIAN]: 278 | estimators = get_estimators_for_mode(secret_mode, power, n_dim) 279 | logq = process_maxlogq(estimators, n_dim, secret_mode, error_dist, security_target, power) 280 | if power == "classical" and secret_mode == MODE_TERNARY: 281 | logq_classical_ternary.append(logq) 282 | elif power == "classical" and secret_mode == MODE_GAUSSIAN: 283 | logq_classical_gaussian.append(logq) 284 | elif power == "quantum" and secret_mode == MODE_TERNARY: 285 | logq_quantum_ternary.append(logq) 286 | elif power == "quantum" and secret_mode == MODE_GAUSSIAN: 287 | logq_quantum_gaussian.append(logq) 288 | 289 | row_format = "| {:<{}} | {:<{}} | {:<{}} ".format( 290 | n_dim, 8, 291 | logq_classical_ternary[0], 17, 292 | logq_classical_gaussian[0], 18 293 | ) 294 | 295 | if include_quantum: 296 | row_format += "| {:<{}} | {:<{}} |".format( 297 | logq_quantum_ternary[0], 15, 298 | logq_quantum_gaussian[0], 16 299 | ) 300 | else: 301 | row_format += "|" 302 | 303 | print(row_format) 304 | print(separator) 305 | 306 | 307 | 308 | 309 | 310 | -------------------------------------------------------------------------------- /RNS-CKKS-examples/lattigo/templates/bootstrapping/failure/table.go: -------------------------------------------------------------------------------- 1 | package failure 2 | 3 | import ( 4 | "math" 5 | "math/big" 6 | 7 | "github.com/tuneinsight/lattigo/v5/utils" 8 | "github.com/tuneinsight/lattigo/v5/utils/bignum" 9 | ) 10 | 11 | // ModifiedIrwinHall estimates PR[||I(X)|| > K] by evaluating equation (1) of https://eprint.iacr.org/2022/024: 12 | // 1 - (2/(h+1)! * (sum_i=0^{K+0.5(h+1)} (-1)^i * binom(h+1, i) * (K + 0.5(h+1) - i)^{h+1}))-1)^{2n} 13 | // This method produces accurate results, but is O(h^3). 14 | func ModifiedIrwinHall(K, h, logSlots int) (logfailure float64) { 15 | 16 | var prec uint = utils.Max(uint(2*h), 512) 17 | 18 | sum := new(big.Float).SetPrec(prec) 19 | 20 | two := new(big.Float).SetPrec(prec).SetInt64(2) 21 | one := new(big.Float).SetPrec(prec).SetInt64(1) 22 | binom := new(big.Float).Set(one) 23 | 24 | for i := 0; i < K+(h+1)>>1; i++ { 25 | 26 | // binom(h+1, i) 27 | if i > 0 { 28 | binom.Mul(binom, new(big.Float).SetPrec(prec).SetInt64(int64(h+2-i))) 29 | binom.Quo(binom, new(big.Float).SetPrec(prec).SetInt64(int64(i))) 30 | } 31 | 32 | // 2 * (K + 0.5(h+1) - i)^(h+1) / (h+1)! 33 | x := new(big.Float).SetPrec(prec).SetFloat64(float64(K) + 0.5*float64(h+1) - float64(i)) 34 | y := new(big.Float).Set(one) 35 | for j := 0; j < h+1; j++ { 36 | y.Mul(y, x) 37 | y.Quo(y, new(big.Float).SetPrec(prec).SetInt64(int64(j+1))) 38 | } 39 | 40 | // binom(h+1, i) * 2 * (K + 0.5(h+1) - i)^(h+1) / (h+1)! 41 | y.Mul(y, binom) 42 | 43 | if i&1 == 0 { 44 | sum.Add(sum, y) 45 | } else { 46 | sum.Sub(sum, y) 47 | } 48 | } 49 | 50 | sum.Mul(sum, two) 51 | sum.Sub(sum, one) 52 | sum.Sub(one, sum) 53 | 54 | if sum.Cmp(new(big.Float)) == -1 { 55 | return math.Inf(-1) 56 | } 57 | 58 | sum = bignum.Log(sum) 59 | sum.Quo(sum, bignum.Log2(prec)) 60 | sumF64, _ := sum.Float64() 61 | return sumF64 + 1 + float64(logSlots) 62 | } 63 | 64 | var F8192 = map[int]float64{ 65 | 1: -0.044729, 66 | 2: -0.090820, 67 | 3: -0.138291, 68 | 4: -0.187158, 69 | 5: -0.237438, 70 | 6: -0.289147, 71 | 7: -0.342300, 72 | 8: -0.396914, 73 | 9: -0.453002, 74 | 10: -0.510580, 75 | 11: -0.569662, 76 | 12: -0.630261, 77 | 13: -0.692393, 78 | 14: -0.756069, 79 | 15: -0.821303, 80 | 16: -0.888107, 81 | 17: -0.956495, 82 | 18: -1.026477, 83 | 19: -1.098067, 84 | 20: -1.171275, 85 | 21: -1.246112, 86 | 22: -1.322590, 87 | 23: -1.400719, 88 | 24: -1.480510, 89 | 25: -1.561972, 90 | 26: -1.645117, 91 | 27: -1.729952, 92 | 28: -1.816488, 93 | 29: -1.904733, 94 | 30: -1.994698, 95 | 31: -2.086389, 96 | 32: -2.179817, 97 | 33: -2.274988, 98 | 34: -2.371912, 99 | 35: -2.470595, 100 | 36: -2.571046, 101 | 37: -2.673272, 102 | 38: -2.777280, 103 | 39: -2.883077, 104 | 40: -2.990670, 105 | 41: -3.100065, 106 | 42: -3.211270, 107 | 43: -3.324291, 108 | 44: -3.439134, 109 | 45: -3.555804, 110 | 46: -3.674308, 111 | 47: -3.794651, 112 | 48: -3.916840, 113 | 49: -4.040878, 114 | 50: -4.166773, 115 | 51: -4.294529, 116 | 52: -4.424150, 117 | 53: -4.555643, 118 | 54: -4.689011, 119 | 55: -4.824259, 120 | 56: -4.961393, 121 | 57: -5.100415, 122 | 58: -5.241332, 123 | 59: -5.384146, 124 | 60: -5.528863, 125 | 61: -5.675486, 126 | 62: -5.824018, 127 | 63: -5.974465, 128 | 64: -6.126829, 129 | 65: -6.281114, 130 | 66: -6.437325, 131 | 67: -6.595463, 132 | 68: -6.755533, 133 | 69: -6.917539, 134 | 70: -7.081482, 135 | 71: -7.247367, 136 | 72: -7.415197, 137 | 73: -7.584974, 138 | 74: -7.756702, 139 | 75: -7.930383, 140 | 76: -8.106020, 141 | 77: -8.283616, 142 | 78: -8.463174, 143 | 79: -8.644697, 144 | 80: -8.828186, 145 | 81: -9.013644, 146 | 82: -9.201075, 147 | 83: -9.390479, 148 | 84: -9.581860, 149 | 85: -9.775221, 150 | 86: -9.970562, 151 | 87: -10.167887, 152 | 88: -10.367197, 153 | 89: -10.568495, 154 | 90: -10.771783, 155 | 91: -10.977062, 156 | 92: -11.184335, 157 | 93: -11.393604, 158 | 94: -11.604870, 159 | 95: -11.818136, 160 | 96: -12.033403, 161 | 97: -12.250673, 162 | 98: -12.469948, 163 | 99: -12.691229, 164 | 100: -12.914518, 165 | 101: -13.139818, 166 | 102: -13.367128, 167 | 103: -13.596452, 168 | 104: -13.827790, 169 | 105: -14.061145, 170 | 106: -14.296517, 171 | 107: -14.533908, 172 | 108: -14.773319, 173 | 109: -15.014753, 174 | 110: -15.258209, 175 | 111: -15.503691, 176 | 112: -15.751198, 177 | 113: -16.000733, 178 | 114: -16.252296, 179 | 115: -16.505889, 180 | 116: -16.761512, 181 | 117: -17.019169, 182 | 118: -17.278858, 183 | 119: -17.540583, 184 | 120: -17.804343, 185 | 121: -18.070140, 186 | 122: -18.337975, 187 | 123: -18.607849, 188 | 124: -18.879763, 189 | 125: -19.153718, 190 | 126: -19.429716, 191 | 127: -19.707757, 192 | 128: -19.987842, 193 | 129: -20.269973, 194 | 130: -20.554150, 195 | 131: -20.840373, 196 | 132: -21.128646, 197 | 133: -21.418967, 198 | 134: -21.711338, 199 | 135: -22.005760, 200 | 136: -22.302233, 201 | 137: -22.600760, 202 | 138: -22.901339, 203 | 139: -23.203973, 204 | 140: -23.508663, 205 | 141: -23.815408, 206 | 142: -24.124209, 207 | 143: -24.435068, 208 | 144: -24.747986, 209 | 145: -25.062963, 210 | 146: -25.379999, 211 | 147: -25.699096, 212 | 148: -26.020254, 213 | 149: -26.343474, 214 | 150: -26.668757, 215 | 151: -26.996103, 216 | 152: -27.325514, 217 | 153: -27.656989, 218 | 154: -27.990530, 219 | 155: -28.326136, 220 | 156: -28.663810, 221 | 157: -29.003551, 222 | 158: -29.345360, 223 | 159: -29.689238, 224 | 160: -30.035185, 225 | 161: -30.383201, 226 | 162: -30.733289, 227 | 163: -31.085447, 228 | 164: -31.439678, 229 | 165: -31.795980, 230 | 166: -32.154355, 231 | 167: -32.514804, 232 | 168: -32.877327, 233 | 169: -33.241924, 234 | 170: -33.608596, 235 | 171: -33.977344, 236 | 172: -34.348168, 237 | 173: -34.721069, 238 | 174: -35.096047, 239 | 175: -35.473103, 240 | 176: -35.852236, 241 | 177: -36.233449, 242 | 178: -36.616741, 243 | 179: -37.002112, 244 | 180: -37.389564, 245 | 181: -37.779096, 246 | 182: -38.170709, 247 | 183: -38.564404, 248 | 184: -38.960182, 249 | 185: -39.358041, 250 | 186: -39.757984, 251 | 187: -40.160010, 252 | 188: -40.564120, 253 | 189: -40.970314, 254 | 190: -41.378593, 255 | 191: -41.788957, 256 | 192: -42.201407, 257 | 193: -42.615943, 258 | 194: -43.032566, 259 | 195: -43.451275, 260 | 196: -43.872071, 261 | 197: -44.294956, 262 | 198: -44.719928, 263 | 199: -45.146989, 264 | 200: -45.576138, 265 | 201: -46.007378, 266 | 202: -46.440706, 267 | 203: -46.876125, 268 | 204: -47.313634, 269 | 205: -47.753234, 270 | 206: -48.194926, 271 | 207: -48.638708, 272 | 208: -49.084583, 273 | 209: -49.532550, 274 | 210: -49.982610, 275 | 211: -50.434763, 276 | 212: -50.889009, 277 | 213: -51.345349, 278 | 214: -51.803783, 279 | 215: -52.264311, 280 | 216: -52.726935, 281 | 217: -53.191653, 282 | 218: -53.658467, 283 | 219: -54.127377, 284 | 220: -54.598383, 285 | 221: -55.071485, 286 | 222: -55.546684, 287 | 223: -56.023980, 288 | 224: -56.503374, 289 | 225: -56.984866, 290 | 226: -57.468456, 291 | 227: -57.954144, 292 | 228: -58.441931, 293 | 229: -58.931817, 294 | 230: -59.423802, 295 | 231: -59.917887, 296 | 232: -60.414072, 297 | 233: -60.912358, 298 | 234: -61.412744, 299 | 235: -61.915231, 300 | 236: -62.419819, 301 | 237: -62.926509, 302 | 238: -63.435300, 303 | 239: -63.946194, 304 | 240: -64.459190, 305 | 241: -64.974289, 306 | 242: -65.491491, 307 | 243: -66.010796, 308 | 244: -66.532204, 309 | 245: -67.055717, 310 | 246: -67.581334, 311 | 247: -68.109055, 312 | 248: -68.638881, 313 | 249: -69.170812, 314 | 250: -69.704848, 315 | 251: -70.240990, 316 | 252: -70.779238, 317 | 253: -71.319591, 318 | 254: -71.862051, 319 | 255: -72.406618, 320 | 256: -72.953292, 321 | 257: -73.502073, 322 | 258: -74.052961, 323 | 259: -74.605958, 324 | 260: -75.161062, 325 | 261: -75.718274, 326 | 262: -76.277595, 327 | 263: -76.839025, 328 | 264: -77.402564, 329 | 265: -77.968213, 330 | 266: -78.535970, 331 | 267: -79.105838, 332 | 268: -79.677816, 333 | 269: -80.251904, 334 | 270: -80.828103, 335 | 271: -81.406413, 336 | 272: -81.986834, 337 | 273: -82.569366, 338 | 274: -83.154010, 339 | 275: -83.740766, 340 | 276: -84.329634, 341 | 277: -84.920615, 342 | 278: -85.513708, 343 | 279: -86.108914, 344 | 280: -86.706233, 345 | 281: -87.305666, 346 | 282: -87.907212, 347 | 283: -88.510872, 348 | 284: -89.116646, 349 | 285: -89.724535, 350 | 286: -90.334538, 351 | 287: -90.946657, 352 | 288: -91.560890, 353 | 289: -92.177239, 354 | 290: -92.795703, 355 | 291: -93.416283, 356 | 292: -94.038980, 357 | 293: -94.663792, 358 | 294: -95.290721, 359 | 295: -95.919767, 360 | 296: -96.550930, 361 | 297: -97.184211, 362 | 298: -97.819609, 363 | 299: -98.457124, 364 | 300: -99.096758, 365 | 301: -99.738510, 366 | 302: -100.382380, 367 | 303: -101.028369, 368 | 304: -101.676477, 369 | 305: -102.326705, 370 | 306: -102.979051, 371 | 307: -103.633518, 372 | 308: -104.290104, 373 | 309: -104.948810, 374 | 310: -105.609637, 375 | 311: -106.272584, 376 | 312: -106.937652, 377 | 313: -107.604841, 378 | 314: -108.274151, 379 | 315: -108.945583, 380 | 316: -109.619137, 381 | 317: -110.294812, 382 | 318: -110.972610, 383 | 319: -111.652530, 384 | 320: -112.334573, 385 | 321: -113.018739, 386 | 322: -113.705028, 387 | 323: -114.393440, 388 | 324: -115.083976, 389 | 325: -115.776636, 390 | 326: -116.471419, 391 | 327: -117.168327, 392 | 328: -117.867360, 393 | 329: -118.568517, 394 | 330: -119.271799, 395 | 331: -119.977206, 396 | 332: -120.684739, 397 | 333: -121.394397, 398 | 334: -122.106181, 399 | 335: -122.820092, 400 | 336: -123.536128, 401 | 337: -124.254291, 402 | 338: -124.974581, 403 | 339: -125.696998, 404 | 340: -126.421542, 405 | 341: -127.148213, 406 | 342: -127.877012, 407 | 343: -128.607939, 408 | 344: -129.340995, 409 | 345: -130.076178, 410 | 346: -130.813490, 411 | 347: -131.552931, 412 | 348: -132.294501, 413 | 349: -133.038200, 414 | 350: -133.784029, 415 | 351: -134.531987, 416 | 352: -135.282075, 417 | 353: -136.034294, 418 | 354: -136.788642, 419 | 355: -137.545122, 420 | 356: -138.303732, 421 | 357: -139.064473, 422 | 358: -139.827346, 423 | 359: -140.592350, 424 | 360: -141.359485, 425 | 361: -142.128753, 426 | 362: -142.900153, 427 | 363: -143.673685, 428 | 364: -144.449350, 429 | 365: -145.227148, 430 | 366: -146.007079, 431 | 367: -146.789143, 432 | 368: -147.573340, 433 | 369: -148.359672, 434 | 370: -149.148137, 435 | 371: -149.938737, 436 | 372: -150.731471, 437 | 373: -151.526339, 438 | 374: -152.323343, 439 | 375: -153.122482, 440 | 376: -153.923756, 441 | 377: -154.727165, 442 | 378: -155.532711, 443 | 379: -156.340392, 444 | 380: -157.150210, 445 | 381: -157.962164, 446 | 382: -158.776255, 447 | 383: -159.592482, 448 | 384: -160.410847, 449 | 385: -161.231350, 450 | 386: -162.053989, 451 | 387: -162.878767, 452 | 388: -163.705683, 453 | 389: -164.534737, 454 | 390: -165.365929, 455 | 391: -166.199261, 456 | 392: -167.034731, 457 | 393: -167.872340, 458 | 394: -168.712089, 459 | 395: -169.553978, 460 | 396: -170.398006, 461 | 397: -171.244175, 462 | 398: -172.092484, 463 | 399: -172.942933, 464 | 400: -173.795524, 465 | 401: -174.650255, 466 | 402: -175.507127, 467 | 403: -176.366142, 468 | 404: -177.227297, 469 | 405: -178.090595, 470 | 406: -178.956035, 471 | 407: -179.823617, 472 | 408: -180.693342, 473 | 409: -181.565210, 474 | 410: -182.439221, 475 | 411: -183.315375, 476 | 412: -184.193673, 477 | 413: -185.074115, 478 | 414: -185.956701, 479 | 415: -186.841431, 480 | 416: -187.728305, 481 | 417: -188.617324, 482 | 418: -189.508489, 483 | 419: -190.401798, 484 | 420: -191.297253, 485 | 421: -192.194853, 486 | 422: -193.094600, 487 | 423: -193.996492, 488 | 424: -194.900531, 489 | 425: -195.806717, 490 | 426: -196.715049, 491 | 427: -197.625529, 492 | 428: -198.538155, 493 | 429: -199.452930, 494 | 430: -200.369852, 495 | 431: -201.288922, 496 | 432: -202.210140, 497 | 433: -203.133507, 498 | 434: -204.059023, 499 | 435: -204.986687, 500 | 436: -205.916501, 501 | 437: -206.848464, 502 | 438: -207.782577, 503 | 439: -208.718840, 504 | 440: -209.657253, 505 | 441: -210.597816, 506 | 442: -211.540530, 507 | 443: -212.485395, 508 | 444: -213.432411, 509 | 445: -214.381578, 510 | 446: -215.332897, 511 | 447: -216.286368, 512 | 448: -217.241991, 513 | 449: -218.199766, 514 | 450: -219.159694, 515 | 451: -220.121775, 516 | 452: -221.086008, 517 | 453: -222.052395, 518 | 454: -223.020936, 519 | 455: -223.991630, 520 | 456: -224.964479, 521 | 457: -225.939481, 522 | 458: -226.916638, 523 | 459: -227.895950, 524 | 460: -228.877417, 525 | 461: -229.861039, 526 | 462: -230.846817, 527 | 463: -231.834750, 528 | 464: -232.824839, 529 | 465: -233.817085, 530 | 466: -234.811487, 531 | 467: -235.808045, 532 | 468: -236.806761, 533 | 469: -237.807634, 534 | 470: -238.810665, 535 | 471: -239.815853, 536 | 472: -240.823199, 537 | 473: -241.832703, 538 | 474: -242.844366, 539 | 475: -243.858187, 540 | 476: -244.874168, 541 | 477: -245.892308, 542 | 478: -246.912607, 543 | 479: -247.935066, 544 | 480: -248.959685, 545 | 481: -249.986464, 546 | 482: -251.015403, 547 | 483: -252.046504, 548 | 484: -253.079765, 549 | 485: -254.115188, 550 | 486: -255.152772, 551 | 487: -256.192517, 552 | 488: -257.234425, 553 | 489: -258.278495, 554 | 490: -259.324728, 555 | 491: -260.373123, 556 | 492: -261.423681, 557 | 493: -262.476403, 558 | 494: -263.531288, 559 | 495: -264.588337, 560 | 496: -265.647550, 561 | 497: -266.708928, 562 | 498: -267.772470, 563 | 499: -268.838176, 564 | 500: -269.906048, 565 | 501: -270.976085, 566 | 502: -272.048288, 567 | 503: -273.122657, 568 | 504: -274.199192, 569 | 505: -275.277893, 570 | 506: -276.358761, 571 | 507: -277.441795, 572 | 508: -278.526997, 573 | 509: -279.614367, 574 | 510: -280.703904, 575 | 511: -281.795609, 576 | 512: -282.889482, 577 | 513: -283.985524, 578 | 514: -285.083735, 579 | 515: -286.184114, 580 | 516: -287.286663, 581 | 517: -288.391382, 582 | 518: -289.498270, 583 | 519: -290.607328, 584 | 520: -291.718557, 585 | 521: -292.831956, 586 | 522: -293.947527, 587 | 523: -295.065268, 588 | 524: -296.185181, 589 | 525: -297.307265, 590 | 526: -298.431522, 591 | 527: -299.557951, 592 | 528: -300.686552, 593 | 529: -301.817326, 594 | 530: -302.950273, 595 | 531: -304.085394, 596 | 532: -305.222688, 597 | 533: -306.362156, 598 | 534: -307.503798, 599 | 535: -308.647614, 600 | 536: -309.793606, 601 | 537: -310.941772, 602 | 538: -312.092113, 603 | 539: -313.244630, 604 | 540: -314.399323, 605 | 541: -315.556192, 606 | 542: -316.715237, 607 | 543: -317.876459, 608 | 544: -319.039857, 609 | 545: -320.205433, 610 | 546: -321.373187, 611 | 547: -322.543118, 612 | 548: -323.715227, 613 | 549: -324.889514, 614 | 550: -326.065980, 615 | 551: -327.244625, 616 | 552: -328.425449, 617 | 553: -329.608452, 618 | 554: -330.793635, 619 | 555: -331.980999, 620 | 556: -333.170542, 621 | 557: -334.362266, 622 | 558: -335.556171, 623 | 559: -336.752256, 624 | 560: -337.950524, 625 | 561: -339.150973, 626 | 562: -340.353604, 627 | 563: -341.558417, 628 | 564: -342.765413, 629 | 565: -343.974591, 630 | 566: -345.185953, 631 | 567: -346.399498, 632 | 568: -347.615227, 633 | 569: -348.833140, 634 | 570: -350.053237, 635 | 571: -351.275518, 636 | 572: -352.499985, 637 | 573: -353.726637, 638 | 574: -354.955474, 639 | 575: -356.186497, 640 | 576: -357.419705, 641 | 577: -358.655101, 642 | 578: -359.892682, 643 | 579: -361.132451, 644 | 580: -362.374407, 645 | 581: -363.618550, 646 | 582: -364.864882, 647 | 583: -366.113401, 648 | 584: -367.364108, 649 | 585: -368.617005, 650 | 586: -369.872090, 651 | 587: -371.129364, 652 | 588: -372.388829, 653 | 589: -373.650483, 654 | 590: -374.914327, 655 | 591: -376.180361, 656 | 592: -377.448587, 657 | 593: -378.719003, 658 | 594: -379.991611, 659 | 595: -381.266410, 660 | 596: -382.543402, 661 | 597: -383.822585, 662 | 598: -385.103961, 663 | 599: -386.387531, 664 | 600: -387.673293, 665 | 601: -388.961249, 666 | 602: -390.251398, 667 | 603: -391.543742, 668 | 604: -392.838280, 669 | 605: -394.135012, 670 | 606: -395.433940, 671 | 607: -396.735063, 672 | 608: -398.038382, 673 | 609: -399.343896, 674 | 610: -400.651607, 675 | 611: -401.961515, 676 | 612: -403.273619, 677 | 613: -404.587920, 678 | 614: -405.904419, 679 | 615: -407.223116, 680 | 616: -408.544011, 681 | 617: -409.867104, 682 | 618: -411.192396, 683 | 619: -412.519887, 684 | 620: -413.849577, 685 | 621: -415.181467, 686 | 622: -416.515557, 687 | 623: -417.851847, 688 | 624: -419.190338, 689 | 625: -420.531029, 690 | 626: -421.873922, 691 | 627: -423.219017, 692 | 628: -424.566313, 693 | 629: -425.915812, 694 | 630: -427.267513, 695 | 631: -428.621417, 696 | 632: -429.977524, 697 | 633: -431.335835, 698 | 634: -432.696349, 699 | 635: -434.059068, 700 | 636: -435.423990, 701 | 637: -436.791118, 702 | 638: -438.160451, 703 | 639: -439.531989, 704 | 640: -440.905733, 705 | 641: -442.281683, 706 | 642: -443.659839, 707 | 643: -445.040202, 708 | 644: -446.422772, 709 | 645: -447.807549, 710 | 646: -449.194534, 711 | 647: -450.583727, 712 | 648: -451.975129, 713 | 649: -453.368739, 714 | 650: -454.764558, 715 | 651: -456.162586, 716 | 652: -457.562824, 717 | 653: -458.965272, 718 | 654: -460.369930, 719 | 655: -461.776799, 720 | 656: -463.185879, 721 | 657: -464.597170, 722 | 658: -466.010673, 723 | 659: -467.426388, 724 | 660: -468.844315, 725 | 661: -470.264455, 726 | 662: -471.686807, 727 | 663: -473.111373, 728 | 664: -474.538153, 729 | 665: -475.967147, 730 | 666: -477.398355, 731 | 667: -478.831777, 732 | 668: -480.267415, 733 | 669: -481.705268, 734 | 670: -483.145336, 735 | 671: -484.587621, 736 | 672: -486.032122, 737 | 673: -487.478840, 738 | 674: -488.927774, 739 | 675: -490.378927, 740 | 676: -491.832296, 741 | 677: -493.287884, 742 | 678: -494.745691, 743 | 679: -496.205716, 744 | 680: -497.667960, 745 | 681: -499.132423, 746 | 682: -500.599107, 747 | 683: -502.068010, 748 | 684: -503.539134, 749 | 685: -505.012479, 750 | 686: -506.488045, 751 | 687: -507.965833, 752 | 688: -509.445842, 753 | 689: -510.928074, 754 | 690: -512.412528, 755 | } 756 | -------------------------------------------------------------------------------- /tables.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, 'lattice-estimator') 3 | from estimator import * 4 | from estimator.lwe_dual import dual_hybrid 5 | from sage.all import oo, log 6 | from functools import partial 7 | 8 | classic_model = RC.BDGL16 9 | quantum_model = RC.LaaMosPol14 10 | 11 | 12 | # Table 5.2 - 128-bit security, ternary secret 13 | 14 | param_1024_ternary_classic_128 = LWE.Parameters( 15 | n = 1024, 16 | q = 2**26, 17 | Xs = ND.UniformMod(3), 18 | Xe = ND.DiscreteGaussian(3.19), 19 | m = oo, 20 | tag = "param_1024_ternary_classic_128" 21 | ) 22 | 23 | param_2048_ternary_classic_128 = LWE.Parameters( 24 | n = 2048, 25 | q = 2**53, 26 | Xs = ND.UniformMod(3), 27 | Xe = ND.DiscreteGaussian(3.19), 28 | m = oo, 29 | tag = "param_2048_ternary_classic_128" 30 | ) 31 | 32 | param_4096_ternary_classic_128 = LWE.Parameters( 33 | n = 4096, 34 | q = 2**106, 35 | Xs = ND.UniformMod(3), 36 | Xe = ND.DiscreteGaussian(3.19), 37 | m = oo, 38 | tag = "param_4096_ternary_classic_128" 39 | ) 40 | 41 | param_8192_ternary_classic_128 = LWE.Parameters( 42 | n = 8192, 43 | q = 2**214, 44 | Xs = ND.UniformMod(3), 45 | Xe = ND.DiscreteGaussian(3.19), 46 | m = oo, 47 | tag = "param_8192_ternary_classic_128" 48 | ) 49 | 50 | param_16384_ternary_classic_128 = LWE.Parameters( 51 | n = 16384, 52 | q = 2**430, 53 | Xs = ND.UniformMod(3), 54 | Xe = ND.DiscreteGaussian(3.19), 55 | m = oo, 56 | tag = "param_16384_ternary_classic_128" 57 | ) 58 | 59 | param_32768_ternary_classic_128 = LWE.Parameters( 60 | n = 32768, 61 | q = 2**868, 62 | Xs = ND.UniformMod(3), 63 | Xe = ND.DiscreteGaussian(3.19), 64 | m = oo, 65 | tag = "param_32768_ternary_classic_128" 66 | ) 67 | 68 | param_65536_ternary_classic_128 = LWE.Parameters( 69 | n = 65536, 70 | q = 2**1747, 71 | Xs = ND.UniformMod(3), 72 | Xe = ND.DiscreteGaussian(3.19), 73 | m = oo, 74 | tag = "param_65536_ternary_classic_128" 75 | ) 76 | 77 | param_131072_ternary_classic_128 = LWE.Parameters( 78 | n = 131072, 79 | q = 2**3523, 80 | Xs = ND.UniformMod(3), 81 | Xe = ND.DiscreteGaussian(3.19), 82 | m = oo, 83 | tag = "param_131072_ternary_classic_128" 84 | ) 85 | 86 | Table_5_2_a = [(param_2048_ternary_classic_128, 128, classic_model), 87 | (param_4096_ternary_classic_128, 128, classic_model), 88 | (param_8192_ternary_classic_128, 128, classic_model), 89 | (param_16384_ternary_classic_128, 128, classic_model), 90 | (param_32768_ternary_classic_128, 128, classic_model), 91 | (param_65536_ternary_classic_128, 128, classic_model), 92 | (param_131072_ternary_classic_128, 128, classic_model)] 93 | 94 | # Table 5.2 - 192-bit security, ternary secret 95 | 96 | param_2048_ternary_classic_192 = LWE.Parameters( 97 | n = 2048, 98 | q = 2**36, 99 | Xs = ND.UniformMod(3), 100 | Xe = ND.DiscreteGaussian(3.19), 101 | m = oo, 102 | tag = "param_2048_ternary_classic_192" 103 | ) 104 | 105 | param_4096_ternary_classic_192 = LWE.Parameters( 106 | n = 4096, 107 | q = 2**73, 108 | Xs = ND.UniformMod(3), 109 | Xe = ND.DiscreteGaussian(3.19), 110 | m = oo, 111 | tag = "param_4096_ternary_classic_192" 112 | ) 113 | 114 | param_8192_ternary_classic_192 = LWE.Parameters( 115 | n = 8192, 116 | q = 2**147, #2**148, 117 | Xs = ND.UniformMod(3), 118 | Xe = ND.DiscreteGaussian(3.19), 119 | m = oo, 120 | tag = "param_8192_ternary_classic_192" 121 | ) 122 | 123 | param_16384_ternary_classic_192 = LWE.Parameters( 124 | n = 16384, 125 | q = 2**297, 126 | Xs = ND.UniformMod(3), 127 | Xe = ND.DiscreteGaussian(3.19), 128 | m = oo, 129 | tag = "param_16384_ternary_classic_192" 130 | ) 131 | 132 | param_32768_ternary_classic_192 = LWE.Parameters( 133 | n = 32768, 134 | q = 2**597, 135 | Xs = ND.UniformMod(3), 136 | Xe = ND.DiscreteGaussian(3.19), 137 | m = oo, 138 | tag = "param_32768_ternary_classic_192" 139 | ) 140 | 141 | param_65536_ternary_classic_192 = LWE.Parameters( 142 | n = 65536, 143 | q = 2**1199, 144 | Xs = ND.UniformMod(3), 145 | Xe = ND.DiscreteGaussian(3.19), 146 | m = oo, 147 | tag = "param_65536_ternary_classic_192" 148 | ) 149 | 150 | param_131072_ternary_classic_192 = LWE.Parameters( 151 | n = 131072, 152 | q = 2**2411, 153 | Xs = ND.UniformMod(3), 154 | Xe = ND.DiscreteGaussian(3.19), 155 | m = oo, 156 | tag = "param_131072_ternary_classic_192" 157 | ) 158 | 159 | Table_5_2_b = [(param_2048_ternary_classic_192, 192, classic_model), 160 | (param_4096_ternary_classic_192, 192, classic_model), 161 | (param_8192_ternary_classic_192, 192, classic_model), 162 | (param_16384_ternary_classic_192, 192, classic_model), 163 | (param_32768_ternary_classic_192, 192, classic_model), 164 | (param_65536_ternary_classic_192, 192, classic_model), 165 | (param_131072_ternary_classic_192, 192, classic_model)] 166 | 167 | # Table 5.2 - 256-bit security, ternary secret 168 | 169 | param_2048_ternary_classic_256 = LWE.Parameters( 170 | n = 2048, 171 | q = 2**27, 172 | Xs = ND.UniformMod(3), 173 | Xe = ND.DiscreteGaussian(3.19), 174 | m = oo, 175 | tag = "param_2048_ternary_classic_256" 176 | ) 177 | 178 | param_4096_ternary_classic_256 = LWE.Parameters( 179 | n = 4096, 180 | q = 2**56, 181 | Xs = ND.UniformMod(3), 182 | Xe = ND.DiscreteGaussian(3.19), 183 | m = oo, 184 | tag = "param_4096_ternary_classic_256" 185 | ) 186 | 187 | param_8192_ternary_classic_256 = LWE.Parameters( 188 | n = 8192, 189 | q = 2**114, 190 | Xs = ND.UniformMod(3), 191 | Xe = ND.DiscreteGaussian(3.19), 192 | m = oo, 193 | tag = "param_8192_ternary_classic_256" 194 | ) 195 | 196 | param_16384_ternary_classic_256 = LWE.Parameters( 197 | n = 16384, 198 | q = 2**230,, 199 | Xs = ND.UniformMod(3), 200 | Xe = ND.DiscreteGaussian(3.19), 201 | m = oo, 202 | tag = "param_16384_ternary_classic_256" 203 | ) 204 | 205 | param_32768_ternary_classic_256 = LWE.Parameters( 206 | n = 32768, 207 | q = 2**462, 208 | Xs = ND.UniformMod(3), 209 | Xe = ND.DiscreteGaussian(3.19), 210 | m = oo, 211 | tag = "param_32768_ternary_classic_256" 212 | ) 213 | 214 | param_65536_ternary_classic_256 = LWE.Parameters( 215 | n = 65536, 216 | q = 2**929, 217 | Xs = ND.UniformMod(3), 218 | Xe = ND.DiscreteGaussian(3.19), 219 | m = oo, 220 | tag = "param_65536_ternary_classic_256" 221 | ) 222 | 223 | param_131072_ternary_classic_256 = LWE.Parameters( 224 | n = 131072, 225 | q = 2**1866, 226 | Xs = ND.UniformMod(3), 227 | Xe = ND.DiscreteGaussian(3.19), 228 | m = oo, 229 | tag = "param_131072_ternary_classic_256" 230 | ) 231 | 232 | Table_5_2_c = [(param_2048_ternary_classic_256, 256, classic_model), 233 | (param_4096_ternary_classic_256, 256, classic_model), 234 | (param_8192_ternary_classic_256, 256, classic_model), 235 | (param_16384_ternary_classic_256, 256, classic_model), 236 | (param_32768_ternary_classic_256, 256, classic_model), 237 | (param_65536_ternary_classic_256, 256, classic_model), 238 | (param_131072_ternary_classic_256, 256, classic_model)] 239 | 240 | 241 | # Table 5.2 - 128-bit security, gaussian secret (sd = 3.19) 242 | param_1024_gaussian_classic_128 = LWE.Parameters( 243 | n = 1024, 244 | q = 2**28, 245 | Xs = ND.DiscreteGaussian(3.19), 246 | Xe = ND.DiscreteGaussian(3.19), 247 | m = oo, 248 | tag = "param_1024_gaussian_classic_128" 249 | ) 250 | 251 | param_2048_gaussian_classic_128 = LWE.Parameters( 252 | n = 2048, 253 | q = 2**55, 254 | Xs = ND.DiscreteGaussian(3.19), 255 | Xe = ND.DiscreteGaussian(3.19), 256 | m = oo, 257 | tag = "param_2048_gaussian_classic_128" 258 | ) 259 | 260 | param_4096_gaussian_classic_128 = LWE.Parameters( 261 | n = 4096, 262 | q = 2**108, 263 | Xs = ND.DiscreteGaussian(3.19), 264 | Xe = ND.DiscreteGaussian(3.19), 265 | m = oo, 266 | tag = "param_4096_gaussian_classic_128" 267 | ) 268 | 269 | param_8192_gaussian_classic_128 = LWE.Parameters( 270 | n = 8192, 271 | q = 2**216, 272 | Xs = ND.DiscreteGaussian(3.19), 273 | Xe = ND.DiscreteGaussian(3.19), 274 | m = oo, 275 | tag = "param_8192_gaussian_classic_128" 276 | ) 277 | 278 | param_16384_gaussian_classic_128 = LWE.Parameters( 279 | n = 16384, 280 | q = 2**432, 281 | Xs = ND.DiscreteGaussian(3.19), 282 | Xe = ND.DiscreteGaussian(3.19), 283 | m = oo, 284 | tag = "param_16384_gaussian_classic_128" 285 | ) 286 | 287 | param_32768_gaussian_classic_128 = LWE.Parameters( 288 | n = 32768, 289 | q = 2**870, 290 | Xs = ND.DiscreteGaussian(3.19), 291 | Xe = ND.DiscreteGaussian(3.19), 292 | m = oo, 293 | tag = "param_32768_gaussian_classic_128" 294 | ) 295 | 296 | param_65536_gaussian_classic_128 = LWE.Parameters( 297 | n = 65536, 298 | q = 2**1749, 299 | Xs = ND.DiscreteGaussian(3.19), 300 | Xe = ND.DiscreteGaussian(3.19), 301 | m = oo, 302 | tag = "param_65536_gaussian_classic_128" 303 | ) 304 | 305 | param_131072_gaussian_classic_128 = LWE.Parameters( 306 | n = 131072, 307 | q = 2**3523, 308 | Xs = ND.DiscreteGaussian(3.19), 309 | Xe = ND.DiscreteGaussian(3.19), 310 | m = oo, 311 | tag = "param_131072_gaussian_classic_128" 312 | ) 313 | 314 | Table_5_2_d = [(param_2048_gaussian_classic_128, 128, classic_model), 315 | (param_4096_gaussian_classic_128, 128, classic_model), 316 | (param_8192_gaussian_classic_128, 128, classic_model), 317 | (param_16384_gaussian_classic_128, 128, classic_model), 318 | (param_32768_gaussian_classic_128, 128, classic_model), 319 | (param_65536_gaussian_classic_128, 128, classic_model), 320 | (param_131072_gaussian_classic_128, 128, classic_model)] 321 | 322 | # Table 5.2 - 192-bit security, gaussian secret 323 | 324 | param_2048_gaussian_classic_192 = LWE.Parameters( 325 | n = 2048, 326 | q = 2**38, 327 | Xs = ND.DiscreteGaussian(3.19), 328 | Xe = ND.DiscreteGaussian(3.19), 329 | m = oo, 330 | tag = "param_2048_gaussian_classic_192" 331 | ) 332 | 333 | param_4096_gaussian_classic_192 = LWE.Parameters( 334 | n = 4096, 335 | q = 2**75, 336 | Xs = ND.DiscreteGaussian(3.19), 337 | Xe = ND.DiscreteGaussian(3.19), 338 | m = oo, 339 | tag = "param_4096_gaussian_classic_192" 340 | ) 341 | 342 | param_8192_gaussian_classic_192 = LWE.Parameters( 343 | n = 8192, 344 | q = 2**149, 345 | Xs = ND.DiscreteGaussian(3.19), 346 | Xe = ND.DiscreteGaussian(3.19), 347 | m = oo, 348 | tag = "param_8192_gaussian_classic_192" 349 | ) 350 | 351 | param_16384_gaussian_classic_192 = LWE.Parameters( 352 | n = 16384, 353 | q = 2**299, 354 | Xs = ND.DiscreteGaussian(3.19), 355 | Xe = ND.DiscreteGaussian(3.19), 356 | m = oo, 357 | tag = "param_16384_gaussian_classic_192" 358 | ) 359 | 360 | param_32768_gaussian_classic_192 = LWE.Parameters( 361 | n = 32768, 362 | q = 2**599, 363 | Xs = ND.DiscreteGaussian(3.19), 364 | Xe = ND.DiscreteGaussian(3.19), 365 | m = oo, 366 | tag = "param_32768_gaussian_classic_192" 367 | ) 368 | 369 | param_65536_gaussian_classic_192 = LWE.Parameters( 370 | n = 65536, 371 | q = 2**1201, 372 | Xs = ND.DiscreteGaussian(3.19), 373 | Xe = ND.DiscreteGaussian(3.19), 374 | m = oo, 375 | tag = "param_65536_gaussian_classic_192" 376 | ) 377 | 378 | param_131072_gaussian_classic_192 = LWE.Parameters( 379 | n = 131072, 380 | q = 2**2313, 381 | Xs = ND.DiscreteGaussian(3.19), 382 | Xe = ND.DiscreteGaussian(3.19), 383 | m = oo, 384 | tag = "param_131072_gaussian_classic_192" 385 | ) 386 | 387 | Table_5_2_e = [(param_2048_gaussian_classic_192, 192, classic_model), 388 | (param_4096_gaussian_classic_192, 192, classic_model), 389 | (param_8192_gaussian_classic_192, 192, classic_model), 390 | (param_16384_gaussian_classic_192, 192, classic_model), 391 | (param_32768_gaussian_classic_192, 192, classic_model), 392 | (param_65536_gaussian_classic_192, 192, classic_model), 393 | (param_131072_gaussian_classic_192, 192, classic_model)] 394 | 395 | 396 | # Table 5.2 - 256-bit security, gaussian secret 397 | 398 | param_2048_gaussian_classic_256 = LWE.Parameters( 399 | n = 2048, 400 | q = 2**30, 401 | Xs = ND.DiscreteGaussian(3.19), 402 | Xe = ND.DiscreteGaussian(3.19), 403 | m = oo, 404 | tag = "param_2048_gaussian_classic_256" 405 | ) 406 | 407 | param_4096_gaussian_classic_256 = LWE.Parameters( 408 | n = 4096, 409 | q = 2**58, 410 | Xs = ND.DiscreteGaussian(3.19), 411 | Xe = ND.DiscreteGaussian(3.19), 412 | m = oo, 413 | tag = "param_4096_gaussian_classic_256" 414 | ) 415 | 416 | param_8192_gaussian_classic_256 = LWE.Parameters( 417 | n = 8192, 418 | q = 2**119, 419 | Xs = ND.DiscreteGaussian(3.19), 420 | Xe = ND.DiscreteGaussian(3.19), 421 | m = oo, 422 | tag = "param_8192_gaussian_classic_256" 423 | ) 424 | 425 | param_8192_gaussian_quantum_256 = LWE.Parameters( 426 | n = 8192, 427 | q = 2**116, 428 | Xs = ND.DiscreteGaussian(3.19), 429 | Xe = ND.DiscreteGaussian(3.19), 430 | m = oo, 431 | tag = "param_8192_gaussian_quantum_256" 432 | ) 433 | 434 | param_16384_gaussian_quantum_256 = LWE.Parameters( 435 | n = 16384, 436 | q = 2**232, 437 | Xs = ND.DiscreteGaussian(3.19), 438 | Xe = ND.DiscreteGaussian(3.19), 439 | m = oo, 440 | tag = "param_16384_gaussian_quantum_256" 441 | ) 442 | 443 | param_32768_gaussian_classic_256 = LWE.Parameters( 444 | n = 32768, 445 | q = 2**464, 446 | Xs = ND.DiscreteGaussian(3.19), 447 | Xe = ND.DiscreteGaussian(3.19), 448 | m = oo, 449 | tag = "param_32768_gaussian_classic_256" 450 | ) 451 | 452 | param_65536_gaussian_classic_256 = LWE.Parameters( 453 | n = 65536, 454 | q = 2**931, 455 | Xs = ND.DiscreteGaussian(3.19), 456 | Xe = ND.DiscreteGaussian(3.19), 457 | m = oo, 458 | tag = "param_65536_gaussian_classic_256" 459 | ) 460 | 461 | param_131072_gaussian_classic_256 = LWE.Parameters( 462 | n = 131072, 463 | q = 2**1868, 464 | Xs = ND.DiscreteGaussian(3.19), 465 | Xe = ND.DiscreteGaussian(3.19), 466 | m = oo, 467 | tag = "param_131072_gaussian_classic_256" 468 | ) 469 | 470 | Table_5_2_f = [(param_2048_gaussian_classic_256, 256, classic_model), 471 | (param_2048_gaussian_quantum_256, 256, quantum_model), 472 | (param_4096_gaussian_classic_256, 256, classic_model), 473 | (param_4096_gaussian_quantum_256, 256, quantum_model), 474 | (param_8192_gaussian_classic_256, 256, classic_model), 475 | (param_8192_gaussian_quantum_256, 256, quantum_model), 476 | (param_16384_gaussian_classic_256, 256, classic_model), 477 | (param_16384_gaussian_quantum_256, 256, quantum_model), 478 | (param_32768_gaussian_classic_256, 256, classic_model), 479 | (param_32768_gaussian_quantum_256, 256, quantum_model), 480 | (param_65536_gaussian_classic_256, 256, classic_model), 481 | (param_65536_gaussian_quantum_256, 256, quantum_model), 482 | (param_131072_gaussian_classic_256, 256, classic_model), 483 | (param_131072_gaussian_quantum_256, 256, quantum_model)] 484 | 485 | 486 | # Table 5.3 487 | 488 | # q = 2**32 489 | 490 | param_tfhe_630_binary_classic_128_32 = LWE.Parameters( 491 | n = 630, 492 | q = 2**32, 493 | Xs = ND.UniformMod(2), 494 | Xe = ND.DiscreteGaussian(2**18.5), 495 | m = oo, 496 | tag = "param_tfhe_630_binary_classic_128_32" 497 | ) 498 | 499 | param_tfhe_630_ternary_classic_128_32 = LWE.Parameters( 500 | n = 630, 501 | q = 2**32, 502 | Xs = ND.UniformMod(3), 503 | Xe = ND.DiscreteGaussian(2**17.2), 504 | m = oo, 505 | tag = "param_tfhe_630_ternary_classic_128_32" 506 | ) 507 | 508 | param_tfhe_630_gaussian_classic_128_32 = LWE.Parameters( 509 | n = 630, 510 | q = 2**32, 511 | Xs = ND.DiscreteGaussian(4), 512 | Xe = ND.DiscreteGaussian(2**14.6), 513 | m = oo, 514 | tag = "param_tfhe_630_gaussian_classic_128_32" 515 | ) 516 | 517 | param_tfhe_1024_binary_classic_128_32 = LWE.Parameters( 518 | n = 1024, 519 | q = 2**32, 520 | Xs = ND.UniformMod(2), 521 | Xe = ND.DiscreteGaussian(2**8.3), 522 | m = oo, 523 | tag = "param_tfhe_1024_binary_classic_128_32" 524 | ) 525 | 526 | param_tfhe_1024_ternary_classic_128_32 = LWE.Parameters( 527 | n = 1024, 528 | q = 2**32, 529 | Xs = ND.UniformMod(3), 530 | Xe = ND.DiscreteGaussian(2**7.1), 531 | m = oo, 532 | tag = "param_tfhe_1024_ternary_classic_128_32" 533 | ) 534 | 535 | param_tfhe_1024_gaussian_classic_128_32 = LWE.Parameters( 536 | n = 1024, 537 | q = 2**32, 538 | Xs = ND.DiscreteGaussian(4), 539 | Xe = ND.DiscreteGaussian(2**4.6), 540 | m = oo, 541 | tag = "param_tfhe_1024_gaussian_classic_128_32" 542 | ) 543 | 544 | param_tfhe_2048_binary_classic_128_32 = LWE.Parameters( 545 | n = 2048, 546 | q = 2**32, 547 | Xs = ND.UniformMod(2), 548 | Xe = ND.DiscreteGaussian(2**2.0), 549 | m = oo, 550 | tag = "param_tfhe_2048_binary_classic_128_32" 551 | ) 552 | 553 | param_tfhe_2048_ternary_classic_128_32 = LWE.Parameters( 554 | n = 2048, 555 | q = 2**32, 556 | Xs = ND.UniformMod(3), 557 | Xe = ND.DiscreteGaussian(2**2.0), 558 | m = oo, 559 | tag = "param_tfhe_2048_ternary_classic_128_32" 560 | ) 561 | 562 | param_tfhe_2048_gaussian_classic_128_32 = LWE.Parameters( 563 | n = 2048, 564 | q = 2**32, 565 | Xs = ND.DiscreteGaussian(4), 566 | Xe = ND.DiscreteGaussian(2**2.0), 567 | m = oo, 568 | tag = "param_tfhe_2048_gaussian_classic_128_32" 569 | ) 570 | 571 | 572 | # q = 2**64 573 | 574 | param_tfhe_630_binary_classic_128 = LWE.Parameters( 575 | n = 630, 576 | q = 2**64, 577 | Xs = ND.UniformMod(2), 578 | Xe = ND.DiscreteGaussian(2**50.5), 579 | m = oo, 580 | tag = "param_tfhe_630_binary_classic_128" 581 | ) 582 | 583 | param_tfhe_630_ternary_classic_128 = LWE.Parameters( 584 | n = 630, 585 | q = 2**64, 586 | Xs = ND.UniformMod(3), 587 | Xe = ND.DiscreteGaussian(2**49.2), 588 | m = oo, 589 | tag = "param_tfhe_630_ternary_classic_128" 590 | ) 591 | 592 | param_tfhe_630_gaussian_classic_128 = LWE.Parameters( 593 | n = 630, 594 | q = 2**64, 595 | Xs = ND.DiscreteGaussian(4), 596 | Xe = ND.DiscreteGaussian(2**46.6), 597 | m = oo, 598 | tag = "param_tfhe_630_gaussian_classic_128" 599 | ) 600 | 601 | param_tfhe_750_binary_classic_128 = LWE.Parameters( 602 | n = 750, 603 | q = 2**64, 604 | Xs = ND.UniformMod(2), 605 | Xe = ND.DiscreteGaussian(2**47.4), 606 | m = oo, 607 | tag = "param_tfhe_750_binary_classic_128" 608 | ) 609 | 610 | param_tfhe_750_ternary_classic_128 = LWE.Parameters( 611 | n = 750, 612 | q = 2**64, 613 | Xs = ND.UniformMod(3), 614 | Xe = ND.DiscreteGaussian(2**46.2), 615 | m = oo, 616 | tag = "param_tfhe_750_ternary_classic_128" 617 | ) 618 | 619 | param_tfhe_750_gaussian_classic_128 = LWE.Parameters( 620 | n = 750, 621 | q = 2**64, 622 | Xs = ND.DiscreteGaussian(4), 623 | Xe = ND.DiscreteGaussian(2**43.5), 624 | m = oo, 625 | tag = "param_tfhe_750_gaussian_classic_128" 626 | ) 627 | 628 | param_tfhe_870_binary_classic_128 = LWE.Parameters( 629 | n = 870, 630 | q = 2**64, 631 | Xs = ND.UniformMod(2), 632 | Xe = ND.DiscreteGaussian(2**44.3), 633 | m = oo, 634 | tag = "param_tfhe_870_binary_classic_128" 635 | ) 636 | 637 | param_tfhe_870_ternary_classic_128 = LWE.Parameters( 638 | n = 870, 639 | q = 2**64, 640 | Xs = ND.UniformMod(3), 641 | Xe = ND.DiscreteGaussian(2**43.1), 642 | m = oo, 643 | tag = "param_tfhe_870_ternary_classic_128" 644 | ) 645 | 646 | param_tfhe_870_gaussian_classic_128 = LWE.Parameters( 647 | n = 870, 648 | q = 2**64, 649 | Xs = ND.DiscreteGaussian(4), 650 | Xe = ND.DiscreteGaussian(2**40.3), 651 | m = oo, 652 | tag = "param_tfhe_870_gaussian_classic_128" 653 | ) 654 | 655 | param_tfhe_1024_binary_classic_128 = LWE.Parameters( 656 | n = 1024, 657 | q = 2**64, 658 | Xs = ND.UniformMod(2), 659 | Xe = ND.DiscreteGaussian(2**40.3), 660 | m = oo, 661 | tag = "param_tfhe_1024_binary_classic_128" 662 | ) 663 | 664 | param_tfhe_1024_ternary_classic_128 = LWE.Parameters( 665 | n = 1024, 666 | q = 2**64, 667 | Xs = ND.UniformMod(3), 668 | Xe = ND.DiscreteGaussian(2**39.1), 669 | m = oo, 670 | tag = "param_tfhe_1024_ternary_classic_128" 671 | ) 672 | 673 | param_tfhe_1024_gaussian_classic_128 = LWE.Parameters( 674 | n = 1024, 675 | q = 2**64, 676 | Xs = ND.DiscreteGaussian(4), 677 | Xe = ND.DiscreteGaussian(2**36.4), 678 | m = oo, 679 | tag = "param_tfhe_1024_gaussian_classic_128" 680 | ) 681 | 682 | param_tfhe_2048_binary_classic_128 = LWE.Parameters( 683 | n = 2048, 684 | q = 2**64, 685 | Xs = ND.UniformMod(2), 686 | Xe = ND.DiscreteGaussian(2**13.7), 687 | m = oo, 688 | tag = "param_tfhe_2048_binary_classic_128" 689 | ) 690 | 691 | param_tfhe_2048_ternary_classic_128 = LWE.Parameters( 692 | n = 2048, 693 | q = 2**64, 694 | Xs = ND.UniformMod(3), 695 | Xe = ND.DiscreteGaussian(2**12.4), 696 | m = oo, 697 | tag = "param_tfhe_2048_ternary_classic_128" 698 | ) 699 | 700 | param_tfhe_2048_gaussian_classic_128 = LWE.Parameters( 701 | n = 2048, 702 | q = 2**64, 703 | Xs = ND.DiscreteGaussian(4), 704 | Xe = ND.DiscreteGaussian(2**10.0), 705 | m = oo, 706 | tag = "param_tfhe_2048_gaussian_classic_128" 707 | ) 708 | 709 | param_tfhe_4096_binary_classic_128 = LWE.Parameters( 710 | n = 4096, 711 | q = 2**64, 712 | Xs = ND.UniformMod(2), 713 | Xe = ND.DiscreteGaussian(2**2.0), 714 | m = oo, 715 | tag = "param_tfhe_4096_binary_classic_128" 716 | ) 717 | 718 | param_tfhe_4096_ternary_classic_128 = LWE.Parameters( 719 | n = 4096, 720 | q = 2**64, 721 | Xs = ND.UniformMod(3), 722 | Xe = ND.DiscreteGaussian(2**2.0), 723 | m = oo, 724 | tag = "param_tfhe_4096_ternary_classic_128" 725 | ) 726 | 727 | param_tfhe_4096_gaussian_classic_128 = LWE.Parameters( 728 | n = 4096, 729 | q = 2**64, 730 | Xs = ND.DiscreteGaussian(4), 731 | Xe = ND.DiscreteGaussian(2**2.0), 732 | m = oo, 733 | tag = "param_tfhe_4096_gaussian_classic_128" 734 | ) 735 | 736 | Table_5_3_a = [ 737 | (param_tfhe_630_binary_classic_128_32, 128, classic_model), 738 | (param_tfhe_630_ternary_classic_128_32, 128, classic_model), 739 | (param_tfhe_630_gaussian_classic_128_32, 128, classic_model), 740 | (param_tfhe_1024_binary_classic_128_32, 128, classic_model), 741 | (param_tfhe_1024_ternary_classic_128_32, 128, classic_model), 742 | (param_tfhe_1024_gaussian_classic_128_32, 128, classic_model), 743 | (param_tfhe_2048_binary_classic_128_32, 128, classic_model), 744 | (param_tfhe_2048_ternary_classic_128_32, 128, classic_model), 745 | (param_tfhe_2048_gaussian_classic_128_32, 128, classic_model), 746 | (param_tfhe_630_binary_classic_128, 128, classic_model), 747 | (param_tfhe_630_ternary_classic_128, 128, classic_model), 748 | (param_tfhe_630_gaussian_classic_128, 128, classic_model), 749 | (param_tfhe_750_binary_classic_128, 128, classic_model), 750 | (param_tfhe_750_ternary_classic_128, 128, classic_model), 751 | (param_tfhe_750_gaussian_classic_128, 128, classic_model), 752 | (param_tfhe_870_binary_classic_128, 128, classic_model), 753 | (param_tfhe_870_ternary_classic_128, 128, classic_model), 754 | (param_tfhe_870_gaussian_classic_128, 128, classic_model), 755 | (param_tfhe_1024_binary_classic_128, 128, classic_model), 756 | (param_tfhe_1024_ternary_classic_128, 128, classic_model), 757 | (param_tfhe_1024_gaussian_classic_128, 128, classic_model), 758 | (param_tfhe_2048_binary_classic_128, 128, classic_model), 759 | (param_tfhe_2048_ternary_classic_128, 128, classic_model), 760 | (param_tfhe_2048_gaussian_classic_128, 128, classic_model), 761 | (param_tfhe_4096_binary_classic_128, 128, classic_model), 762 | (param_tfhe_4096_ternary_classic_128, 128, classic_model), 763 | (param_tfhe_4096_gaussian_classic_128, 128, classic_model)] 764 | 765 | 766 | # q = 2**32 767 | 768 | param_tfhe_630_binary_classic_192_32 = LWE.Parameters( 769 | n = 630, 770 | q = 2**32, 771 | Xs = ND.UniformMod(2), 772 | Xe = ND.DiscreteGaussian(2**22.1), 773 | m = oo, 774 | tag = "param_tfhe_630_binary_classic_192_32" 775 | ) 776 | 777 | param_tfhe_630_ternary_classic_192_32 = LWE.Parameters( 778 | n = 630, 779 | q = 2**32, 780 | Xs = ND.UniformMod(3), 781 | Xe = ND.DiscreteGaussian(2**20.8), 782 | m = oo, 783 | tag = "param_tfhe_630_ternary_classic_192_32" 784 | ) 785 | 786 | param_tfhe_630_gaussian_classic_192_32 = LWE.Parameters( 787 | n = 630, 788 | q = 2**32, 789 | Xs = ND.DiscreteGaussian(4), 790 | Xe = ND.DiscreteGaussian(2**17.9), 791 | m = oo, 792 | tag = "param_tfhe_630_gaussian_classic_192_32" 793 | ) 794 | 795 | param_tfhe_1024_binary_classic_192_32 = LWE.Parameters( 796 | n = 1024, 797 | q = 2**32, 798 | Xs = ND.UniformMod(2), 799 | Xe = ND.DiscreteGaussian(2**17.2), 800 | m = oo, 801 | tag = "param_tfhe_1024_binary_classic_192_32" 802 | ) 803 | 804 | param_tfhe_1024_ternary_classic_192_32 = LWE.Parameters( 805 | n = 1024, 806 | q = 2**32, 807 | Xs = ND.UniformMod(3), 808 | Xe = ND.DiscreteGaussian(2**15.9), 809 | m = oo, 810 | tag = "param_tfhe_1024_ternary_classic_192_32" 811 | ) 812 | 813 | param_tfhe_1024_gaussian_classic_192_32 = LWE.Parameters( 814 | n = 1024, 815 | q = 2**32, 816 | Xs = ND.DiscreteGaussian(4), 817 | Xe = ND.DiscreteGaussian(2**13.0), 818 | m = oo, 819 | tag = "param_tfhe_1024_gaussian_classic_192_32" 820 | ) 821 | 822 | param_tfhe_2048_binary_classic_192_32 = LWE.Parameters( 823 | n = 2048, 824 | q = 2**32, 825 | Xs = ND.UniformMod(2), 826 | Xe = ND.DiscreteGaussian(4), 827 | m = oo, 828 | tag = "param_tfhe_2048_binary_classic_192_32" 829 | ) 830 | 831 | param_tfhe_2048_ternary_classic_192_32 = LWE.Parameters( 832 | n = 2048, 833 | q = 2**32, 834 | Xs = ND.UniformMod(3), 835 | Xe = ND.DiscreteGaussian(4), 836 | m = oo, 837 | tag = "param_tfhe_2048_ternary_classic_192_32" 838 | ) 839 | 840 | param_tfhe_2048_gaussian_classic_192_32 = LWE.Parameters( 841 | n = 2048, 842 | q = 2**32, 843 | Xs = ND.DiscreteGaussian(4), 844 | Xe = ND.DiscreteGaussian(4), 845 | m = oo, 846 | tag = "param_tfhe_2048_gaussian_classic_192_32" 847 | ) 848 | 849 | # q = 2**64 850 | 851 | param_tfhe_750_binary_classic_192 = LWE.Parameters( 852 | n = 750, 853 | q = 2**64, 854 | Xs = ND.UniformMod(2), 855 | Xe = ND.DiscreteGaussian(2**52.0), 856 | m = oo, 857 | tag = "param_tfhe_750_binary_classic_192" 858 | ) 859 | 860 | param_tfhe_750_ternary_classic_192 = LWE.Parameters( 861 | n = 750, 862 | q = 2**64, 863 | Xs = ND.UniformMod(3), 864 | Xe = ND.DiscreteGaussian(2**50.6), 865 | m = oo, 866 | tag = "param_tfhe_750_ternary_classic_192" 867 | ) 868 | 869 | param_tfhe_750_gaussian_classic_192 = LWE.Parameters( 870 | n = 750, 871 | q = 2**64, 872 | Xs = ND.DiscreteGaussian(4), 873 | Xe = ND.DiscreteGaussian(2**47.7), 874 | m = oo, 875 | tag = "param_tfhe_750_gaussian_classic_192" 876 | ) 877 | 878 | param_tfhe_870_binary_classic_192 = LWE.Parameters( 879 | n = 870, 880 | q = 2**64, 881 | Xs = ND.UniformMod(2), 882 | Xe = ND.DiscreteGaussian(2**52.0), 883 | m = oo, 884 | tag = "param_tfhe_870_binary_classic_192" 885 | ) 886 | 887 | param_tfhe_870_ternary_classic_192 = LWE.Parameters( 888 | n = 870, 889 | q = 2**64, 890 | Xs = ND.UniformMod(3), 891 | Xe = ND.DiscreteGaussian(2**50.6), 892 | m = oo, 893 | tag = "param_tfhe_870_ternary_classic_192" 894 | ) 895 | 896 | param_tfhe_870_gaussian_classic_192 = LWE.Parameters( 897 | n = 870, 898 | q = 2**64, 899 | Xs = ND.DiscreteGaussian(4), 900 | Xe = ND.DiscreteGaussian(2**47.7), 901 | m = oo, 902 | tag = "param_tfhe_870_gaussian_classic_192" 903 | ) 904 | 905 | param_tfhe_1024_binary_classic_192 = LWE.Parameters( 906 | n = 1024, 907 | q = 2**64, 908 | Xs = ND.UniformMod(2), 909 | Xe = ND.DiscreteGaussian(2**49.2), 910 | m = oo, 911 | tag = "param_tfhe_1024_binary_classic_192" 912 | ) 913 | 914 | param_tfhe_1024_ternary_classic_192 = LWE.Parameters( 915 | n = 1024, 916 | q = 2**64, 917 | Xs = ND.UniformMod(3), 918 | Xe = ND.DiscreteGaussian(2**47.9), 919 | m = oo, 920 | tag = "param_tfhe_1024_ternary_classic_192" 921 | ) 922 | 923 | param_tfhe_1024_gaussian_classic_192 = LWE.Parameters( 924 | n = 1024, 925 | q = 2**64, 926 | Xs = ND.DiscreteGaussian(4), 927 | Xe = ND.DiscreteGaussian(2**45.0), 928 | m = oo, 929 | tag = "param_tfhe_1024_gaussian_classic_192" 930 | ) 931 | 932 | param_tfhe_2048_binary_classic_192 = LWE.Parameters( 933 | n = 2048, 934 | q = 2**64, 935 | Xs = ND.UniformMod(2), 936 | Xe = ND.DiscreteGaussian(2**30.9), 937 | m = oo, 938 | tag = "param_tfhe_2048_binary_classic_192" 939 | ) 940 | 941 | param_tfhe_2048_ternary_classic_192 = LWE.Parameters( 942 | n = 2048, 943 | q = 2**64, 944 | Xs = ND.UniformMod(3), 945 | Xe = ND.DiscreteGaussian(2**29.5), 946 | m = oo, 947 | tag = "param_tfhe_2048_ternary_classic_192" 948 | ) 949 | 950 | param_tfhe_2048_gaussian_classic_192 = LWE.Parameters( 951 | n = 2048, 952 | q = 2**64, 953 | Xs = ND.DiscreteGaussian(4), 954 | Xe = ND.DiscreteGaussian(2**26.5), 955 | m = oo, 956 | tag = "param_tfhe_2048_gaussian_classic_192" 957 | ) 958 | 959 | param_tfhe_4096_binary_classic_192 = LWE.Parameters( 960 | n = 4096, 961 | q = 2**64, 962 | Xs = ND.UniformMod(2), 963 | Xe = ND.DiscreteGaussian(2**2.0), 964 | m = oo, 965 | tag = "param_tfhe_4096_binary_classic_192" 966 | ) 967 | 968 | param_tfhe_4096_ternary_classic_192 = LWE.Parameters( 969 | n = 4096, 970 | q = 2**64, 971 | Xs = ND.UniformMod(3), 972 | Xe = ND.DiscreteGaussian(2**2.0), 973 | m = oo, 974 | tag = "param_tfhe_4096_ternary_classic_192" 975 | ) 976 | 977 | param_tfhe_4096_gaussian_classic_192 = LWE.Parameters( 978 | n = 4096, 979 | q = 2**64, 980 | Xs = ND.DiscreteGaussian(4), 981 | Xe = ND.DiscreteGaussian(2**2.0), 982 | m = oo, 983 | tag = "param_tfhe_4096_gaussian_classic_192" 984 | ) 985 | 986 | Table_5_3_b = [ 987 | (param_tfhe_1024_binary_classic_192_32, 192, classic_model), 988 | (param_tfhe_1024_ternary_classic_192_32, 192, classic_model), 989 | (param_tfhe_1024_gaussian_classic_192_32, 192, classic_model), 990 | (param_tfhe_2048_binary_classic_192_32, 192, classic_model), 991 | (param_tfhe_2048_ternary_classic_192_32, 192, classic_model), 992 | (param_tfhe_2048_gaussian_classic_192_32, 192, classic_model), 993 | (param_tfhe_630_binary_classic_192, 192, classic_model), 994 | (param_tfhe_630_ternary_classic_192, 192, classic_model), 995 | (param_tfhe_630_gaussian_classic_192, 192, classic_model), 996 | (param_tfhe_750_binary_classic_192, 192, classic_model), 997 | (param_tfhe_750_ternary_classic_192, 192, classic_model), 998 | (param_tfhe_750_gaussian_classic_192, 192, classic_model), 999 | (param_tfhe_870_binary_classic_192, 192, classic_model), 1000 | (param_tfhe_870_ternary_classic_192, 192, classic_model), 1001 | (param_tfhe_870_gaussian_classic_192, 192, classic_model), 1002 | (param_tfhe_1024_binary_classic_192, 192, classic_model), 1003 | (param_tfhe_1024_ternary_classic_192, 192, classic_model), 1004 | (param_tfhe_1024_gaussian_classic_192, 192, classic_model), 1005 | (param_tfhe_2048_binary_classic_192, 192, classic_model), 1006 | (param_tfhe_2048_ternary_classic_192, 192, classic_model), 1007 | (param_tfhe_2048_gaussian_classic_192, 192, classic_model), 1008 | (param_tfhe_4096_binary_classic_192, 192, classic_model), 1009 | (param_tfhe_4096_ternary_classic_192, 192, classic_model), 1010 | (param_tfhe_4096_gaussian_classic_192, 192, classic_model)] 1011 | # q = 2**32 1012 | 1013 | param_tfhe_1024_binary_classic_256_32 = LWE.Parameters( 1014 | n = 1024, 1015 | q = 2**32, 1016 | Xs = ND.UniformMod(2), 1017 | Xe = ND.DiscreteGaussian(2**21.8), 1018 | m = oo, 1019 | tag = "param_tfhe_1024_binary_classic_256_32" 1020 | ) 1021 | 1022 | param_tfhe_1024_ternary_classic_256_32 = LWE.Parameters( 1023 | n = 1024, 1024 | q = 2**32, 1025 | Xs = ND.UniformMod(3), 1026 | Xe = ND.DiscreteGaussian(2**20.5), 1027 | m = oo, 1028 | tag = "param_tfhe_1024_ternary_classic_256_32" 1029 | ) 1030 | 1031 | param_tfhe_1024_gaussian_classic_256_32 = LWE.Parameters( 1032 | n = 1024, 1033 | q = 2**32, 1034 | Xs = ND.DiscreteGaussian(4), 1035 | Xe = ND.DiscreteGaussian(2**17.4), 1036 | m = oo, 1037 | tag = "param_tfhe_1024_gaussian_classic_256_32" 1038 | ) 1039 | 1040 | param_tfhe_2048_binary_classic_256_32 = LWE.Parameters( 1041 | n = 2048, 1042 | q = 2**32, 1043 | Xs = ND.UniformMod(2), 1044 | Xe = ND.DiscreteGaussian(2**7.6), 1045 | m = oo, 1046 | tag = "param_tfhe_2048_binary_classic_256_32" 1047 | ) 1048 | 1049 | param_tfhe_2048_ternary_classic_256_32 = LWE.Parameters( 1050 | n = 2048, 1051 | q = 2**32, 1052 | Xs = ND.UniformMod(3), 1053 | Xe = ND.DiscreteGaussian(2**6.1), 1054 | m = oo, 1055 | tag = "param_tfhe_2048_ternary_classic_256_32" 1056 | ) 1057 | 1058 | param_tfhe_2048_gaussian_classic_256_32 = LWE.Parameters( 1059 | n = 2048, 1060 | q = 2**32, 1061 | Xs = ND.DiscreteGaussian(4), 1062 | Xe = ND.DiscreteGaussian(2**3.2), 1063 | m = oo, 1064 | tag = "param_tfhe_2048_gaussian_classic_256_32" 1065 | ) 1066 | 1067 | 1068 | # q = 2**64 1069 | 1070 | param_tfhe_1024_binary_classic_256 = LWE.Parameters( 1071 | n = 1024, 1072 | q = 2**64, 1073 | Xs = ND.UniformMod(2), 1074 | Xe = ND.DiscreteGaussian(2**53.8), 1075 | m = oo, 1076 | tag = "param_tfhe_1024_binary_classic_256" 1077 | ) 1078 | 1079 | param_tfhe_1024_ternary_classic_256 = LWE.Parameters( 1080 | n = 1024, 1081 | q = 2**64, 1082 | Xs = ND.UniformMod(3), 1083 | Xe = ND.DiscreteGaussian(2**52.5), 1084 | m = oo, 1085 | tag = "param_tfhe_1024_ternary_classic_256" 1086 | ) 1087 | 1088 | param_tfhe_1024_gaussian_classic_256 = LWE.Parameters( 1089 | n = 1024, 1090 | q = 2**64, 1091 | Xs = ND.DiscreteGaussian(4), 1092 | Xe = ND.DiscreteGaussian(2**49.4), 1093 | m = oo, 1094 | tag = "param_tfhe_1024_gaussian_classic_256" 1095 | ) 1096 | 1097 | param_tfhe_2048_binary_classic_256 = LWE.Parameters( 1098 | n = 2048, 1099 | q = 2**64, 1100 | Xs = ND.UniformMod(2), 1101 | Xe = ND.DiscreteGaussian(2*39.6), 1102 | m = oo, 1103 | tag = "param_tfhe_2048_binary_classic_256" 1104 | ) 1105 | 1106 | param_tfhe_2048_ternary_classic_256 = LWE.Parameters( 1107 | n = 2048, 1108 | q = 2**64, 1109 | Xs = ND.UniformMod(3), 1110 | Xe = ND.DiscreteGaussian(2**38.1), 1111 | m = oo, 1112 | tag = "param_tfhe_2048_ternary_classic_256" 1113 | ) 1114 | 1115 | param_tfhe_2048_gaussian_classic_256 = LWE.Parameters( 1116 | n = 2048, 1117 | q = 2**64, 1118 | Xs = ND.DiscreteGaussian(4), 1119 | Xe = ND.DiscreteGaussian(2**35.0), 1120 | m = oo, 1121 | tag = "param_tfhe_2048_gaussian_classic_256" 1122 | ) 1123 | 1124 | param_tfhe_4096_binary_classic_256 = LWE.Parameters( 1125 | n = 4096, 1126 | q = 2**64, 1127 | Xs = ND.UniformMod(2), 1128 | Xe = ND.DiscreteGaussian(2**10.9), 1129 | m = oo, 1130 | tag = "param_tfhe_4096_binary_classic_256" 1131 | ) 1132 | 1133 | param_tfhe_4096_ternary_classic_256 = LWE.Parameters( 1134 | n = 4096, 1135 | q = 2**64, 1136 | Xs = ND.UniformMod(3), 1137 | Xe = ND.DiscreteGaussian(2**9.3), 1138 | m = oo, 1139 | tag = "param_tfhe_4096_ternary_classic_256" 1140 | ) 1141 | 1142 | param_tfhe_4096_gaussian_classic_256 = LWE.Parameters( 1143 | n = 4096, 1144 | q = 2**64, 1145 | Xs = ND.DiscreteGaussian(4), 1146 | Xe = ND.DiscreteGaussian(2**6.4), 1147 | m = oo, 1148 | tag = "param_tfhe_4096_gaussian_classic_256" 1149 | ) 1150 | 1151 | param_tfhe_8192_binary_classic_256 = LWE.Parameters( 1152 | n = 8192, 1153 | q = 2**64, 1154 | Xs = ND.UniformMod(2), 1155 | Xe = ND.DiscreteGaussian(2**2), 1156 | m = oo, 1157 | tag = "param_tfhe_8192_binary_quantum_256" 1158 | ) 1159 | 1160 | 1161 | Table_5_3_c = [ 1162 | (param_tfhe_1024_binary_classic_256_32, 256, classic_model), 1163 | (param_tfhe_1024_ternary_classic_256_32, 256, classic_model), 1164 | (param_tfhe_1024_gaussian_classic_256_32, 256, classic_model), 1165 | (param_tfhe_2048_binary_classic_256_32, 256, classic_model), 1166 | (param_tfhe_2048_ternary_classic_256_32, 256, classic_model), 1167 | (param_tfhe_2048_gaussian_classic_256_32, 256, classic_model), 1168 | (param_tfhe_1024_binary_classic_256, 256, classic_model), 1169 | (param_tfhe_1024_ternary_classic_256, 256, classic_model), 1170 | (param_tfhe_1024_gaussian_classic_256, 256, classic_model), 1171 | (param_tfhe_2048_binary_classic_256, 256, classic_model), 1172 | (param_tfhe_2048_ternary_classic_256, 256, classic_model), 1173 | (param_tfhe_2048_gaussian_classic_256, 256, classic_model), 1174 | (param_tfhe_4096_binary_classic_256, 256, classic_model), 1175 | (param_tfhe_4096_ternary_classic_256, 256, classic_model), 1176 | (param_tfhe_4096_gaussian_classic_256, 256, classic_model), 1177 | (param_tfhe_8192_binary_classic_256, 256, classic_model)] 1178 | 1179 | Tables = [Table_5_2_a, 1180 | Table_5_2_b, 1181 | Table_5_2_c, 1182 | Table_5_2_d, 1183 | Table_5_2_e, 1184 | Table_5_2_f, 1185 | Table_5_3_a, 1186 | Table_5_3_b, 1187 | Table_5_3_c] 1188 | 1189 | def test_it(param, sec): 1190 | 1191 | rops = [] 1192 | try: 1193 | est1 = LWE.primal_usvp(param[0], red_cost_model = param[2]) 1194 | rops.append(est1["rop"]) 1195 | except: 1196 | pass 1197 | try: 1198 | est2 = LWE.primal_bdd(param[0], red_cost_model = param[2]) 1199 | rops.append(est2["rop"]) 1200 | except: 1201 | pass 1202 | try: 1203 | est3 = dh(param[0], red_cost_model = param[2]) 1204 | rops.append(est3["rop"]) 1205 | except: 1206 | pass 1207 | 1208 | if log(min(rops),2) < sec: 1209 | print("parameter set {} needs updating".format(param)) 1210 | print("the stddev is {}".format(log(param[0].Xe.stddev,2))) 1211 | print("logq is: {}".format(log(param[0].q,2))) 1212 | 1213 | return 0 1214 | 1215 | 1216 | def test_all_tables(): 1217 | for table in Tables: 1218 | for param in table: 1219 | test_it(param, param[1]) 1220 | return 0 1221 | 1222 | test_all_tables() 1223 | --------------------------------------------------------------------------------