├── FFT.cpp ├── FFT.h ├── FHEW.cpp ├── FHEW.h ├── LICENSE ├── LWE.cpp ├── LWE.h ├── Makefile ├── README.md ├── TODO ├── cmd ├── common.cpp ├── common.h ├── dec.cpp ├── enc.cpp ├── gate.cpp ├── gen.cpp └── nand.cpp ├── distrib.cpp ├── distrib.h ├── fhewTest.cpp └── params.h /FFT.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "FFT.h" 4 | #include "params.h" 5 | 6 | double *in; 7 | fftw_complex *out; 8 | fftw_plan plan_fft_forw, plan_fft_back; 9 | 10 | void FFTsetup() { 11 | in = (double*) fftw_malloc(sizeof(double) * 2*N); 12 | out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * (N + 2)); 13 | plan_fft_forw = fftw_plan_dft_r2c_1d(2*N, in, out, FFTW_PATIENT); 14 | plan_fft_back = fftw_plan_dft_c2r_1d(2*N, out, in, FFTW_PATIENT); 15 | } 16 | 17 | void FFTforward(Ring_FFT res, const Ring_ModQ val) { 18 | for (int k = 0; k < N; ++k) { 19 | in[k] = (double) (val[k]); 20 | in[k+N] = 0.0; 21 | } 22 | fftw_execute(plan_fft_forw); 23 | for (int k = 0; k < N2; ++k) 24 | res[k] = (double complex) out[2*k+1]; 25 | } 26 | 27 | void FFTbackward(Ring_ModQ res, const Ring_FFT val){ 28 | for (int k = 0; k < N2; ++k) { 29 | out[2*k+1] = (double complex) val[k]/N; 30 | out[2*k] = (double complex) 0; 31 | } 32 | fftw_execute(plan_fft_back); 33 | for (int k = 0; k < N; ++k) 34 | res[k] = (long int) round(in[k]); 35 | } 36 | -------------------------------------------------------------------------------- /FFT.h: -------------------------------------------------------------------------------- 1 | #ifndef FFT_H 2 | #define FFT_H 3 | 4 | #include "params.h" 5 | 6 | void FFTsetup(); 7 | void FFTforward(Ring_FFT res, const Ring_ModQ val); 8 | void FFTbackward(Ring_ModQ res, const Ring_FFT val); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /FHEW.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "FHEW.h" 4 | #include "FFT.h" 5 | #include 6 | 7 | using namespace std; 8 | namespace FHEW { 9 | 10 | typedef Ring_ModQ ct_ModQ[K2][2]; // Ciphertext in coefficient form 11 | typedef Ring_ModQ ct_ModQ1[2]; // Entry C[1] of ct_ModQ 12 | typedef Ring_ModQ dct_ModQ[K2][K2]; // Decomposed Ciphertext in coeff form 13 | typedef Ring_ModQ dct_ModQ1[K2]; // Entry C[1] of dct_ModQ 14 | typedef Ring_FFT dct_FFT[K2][K2]; // Decomposed Ciphertext in FFT form 15 | typedef Ring_FFT dct_FFT1[K2]; // Entry C[1] of dct_FFT 16 | 17 | Ring_FFT t_TestMSB; 18 | 19 | void Setup() { 20 | FFTsetup(); 21 | Ring_ModQ tmsb; 22 | tmsb[0]=-1; 23 | for (int i = 1; i < N; ++i) tmsb[i]=1; 24 | FFTforward(t_TestMSB, tmsb); 25 | } 26 | 27 | void FHEWencrypt(ct_FFT ct, Ring_FFT sk_FFT, int m) { // Used by BootstrappingKeyGen 28 | Ring_FFT ai; 29 | ct_ModQ res; 30 | int mm = (((m % q) + q) % q) * (2*N/q); // Reduce mod q (dealing with negative number as well) 31 | int sign = 1; 32 | if (mm >= N) { mm -= N; sign = -1; } 33 | 34 | for (int i = 0; i < K2; ++i) { 35 | for (int k = 0; k < N; ++k) res[i][0][k] = rand(); // % Q 36 | FFTforward(ai, res[i][0]); 37 | for (int k = 0; k < N2; ++k) 38 | ai[k] = ((double complex) ai[k]) * ((double complex) sk_FFT[k]); 39 | FFTbackward(res[i][1], ai); 40 | for (int k = 0; k < N; ++k) res[i][1][k] += Sample(Chi1); // Add error [a,as+e] 41 | } 42 | for (int i = 0; i < K; ++i) { 43 | res[2*i ][0][mm] += sign*vgprime[i]; // Add G Multiple 44 | res[2*i+1][1][mm] += sign*vgprime[i]; // [a,as+e] + X^m *G 45 | } 46 | for (int i = 0; i < K2; ++i) 47 | for (int j = 0; j < 2; ++j) 48 | FFTforward(ct[i][j], res[i][j]); 49 | } 50 | 51 | void KeyGen(EvalKey* EK, const LWE::SecretKey LWEsk) { 52 | LWE::SecretKeyN FHEWsk; 53 | LWE::KeyGenN(FHEWsk); 54 | LWE::SwitchingKeyGen(EK->KSkey, LWEsk, FHEWsk); 55 | 56 | Ring_FFT FHEWskFFT; 57 | FFTforward(FHEWskFFT, FHEWsk); 58 | for (int i = 0; i < n; ++i) 59 | for (int j = 1; j < BS_base; ++j) 60 | for (int k = 0; k < BS_exp; ++k) { 61 | EK->BSkey[i][j][k] = (ct_FFT*) fftw_malloc(sizeof(ct_FFT)); 62 | FHEWencrypt( (*EK->BSkey[i][j][k]), FHEWskFFT, LWEsk[i] * j * BS_table[k] ); 63 | } 64 | } 65 | 66 | void fwrite_ek(const EvalKey& EK, FILE* f) { 67 | // Write bootstrapping key 68 | for (int i = 0; i < n; ++i) 69 | for (int j = 1; j < BS_base; ++j) 70 | for (int k = 0; k < BS_exp; ++k) 71 | assert(fwrite(EK.BSkey[i][j][k], sizeof(ct_FFT), 1, f)); 72 | // Write switching key 73 | for (int i = 0; i < N; ++i) 74 | for (int j = 0; j < KS_base; ++j) 75 | for (int k = 0; k < KS_exp; ++k) 76 | assert(fwrite(EK.KSkey[i][j][k], sizeof(LWE::CipherTextQ), 1, f)); 77 | } 78 | 79 | EvalKey* fread_ek(FILE* f) { 80 | EvalKey* EK = new EvalKey; 81 | // Read bootstrapping key 82 | for (int i = 0; i < n; ++i) 83 | for (int j = 1; j < BS_base; ++j) 84 | for (int k = 0; k < BS_exp; ++k) { 85 | EK->BSkey[i][j][k] = (ct_FFT*) fftw_malloc(sizeof(ct_FFT)); 86 | assert(fread(EK->BSkey[i][j][k], sizeof(ct_FFT), 1, f)); 87 | } 88 | // Read switching key 89 | cerr << "BSKey Read. \n"; 90 | for (int i = 0; i < N; ++i) 91 | for (int j = 0; j < KS_base; ++j) 92 | for (int k = 0; k < KS_exp; ++k) { 93 | EK->KSkey[i][j][k] = new LWE::CipherTextQ; 94 | assert(fread(EK->KSkey[i][j][k], sizeof(LWE::CipherTextQ), 1, f)); 95 | } 96 | return EK; 97 | } 98 | 99 | typedef Ring_FFT ct_FFT1[2]; // C[1] entry of ct_FFT ciphertext 100 | 101 | void AddToACC(ct_FFT1 ACC, ct_FFT C) { 102 | ct_ModQ1 ct; 103 | dct_ModQ1 dct; 104 | dct_FFT1 dctFFT; 105 | // Decompose_ct(dctFFT, ACC); 106 | for (int j = 0; j < 2; ++j) 107 | FFTbackward(ct[j], ACC[j]); 108 | for (int j = 0; j < 2; ++j) 109 | for (int k = 0; k < N; ++k) { 110 | ZmodQ t = ct[j][k] * v_inverse; 111 | for (int l = 0; l < K; ++l) { 112 | ZmodQ r = (t << g_bits_32[l]) >> g_bits_32[l]; 113 | // if ((l==2) && (k ==0 )) 114 | // cout << r << ","; 115 | t = (t-r) >> g_bits[l]; 116 | dct[j+2*l][k] = r; 117 | } 118 | } 119 | for (int j = 0; j < K2; ++j) 120 | FFTforward(dctFFT[j], dct[j]); 121 | // Mult_dct_ct(ACC, dct, C); 122 | for (int j = 0; j < 2; ++j) 123 | for (int k = 0; k < N2; ++k) { 124 | ACC[j][k] = (double complex) 0.0; 125 | for (int l = 0; l < K2; ++l) 126 | ACC[j][k] += ((double complex) dctFFT[l][k]) * ((double complex) C[l][j][k]); 127 | } 128 | } 129 | 130 | void InitializeACC(ct_FFT1 ACC, int m) { // Set a ciphertext to X^m * G (encryption of m without errors) 131 | ct_ModQ1 res; 132 | int mm = (((m % q) + q) % q) * (2*N/q); // Reduce mod q (dealing with negative number as well) 133 | int sign = 1; 134 | if (mm >= N) { mm -= N; sign = -1; } 135 | 136 | for (int j = 0; j < 2; ++j) 137 | for (int k = 0; k < N; ++k) 138 | res[j][k]=0; 139 | res[1][mm] += sign*vgprime[0]; // [a,as+e] + X^m *G 140 | for (int j = 0; j < 2; ++j) 141 | FFTforward(ACC[j], res[j]); 142 | } 143 | 144 | LWE::CipherTextQN* MemberTest(Ring_FFT t, ct_FFT1 C) { 145 | Ring_FFT temp; 146 | Ring_ModQ temp_ModQ; 147 | 148 | LWE::CipherTextQN* ct = new LWE::CipherTextQN; 149 | for (int i = 0; i < N2; ++i) 150 | temp[i] = conj(((double complex) C[0][i]) * ((double complex)t[i])); // Compute t*a 151 | FFTbackward(temp_ModQ, temp); 152 | for (int i = 0; i < N; ++i) ct->a[i] = temp_ModQ[i]; 153 | for (int i = 0; i < N2; ++i) 154 | temp[i] = ((double complex) C[1][i]) * ((double complex) t[i]); 155 | FFTbackward(temp_ModQ, temp); 156 | ct->b = v+temp_ModQ[0]; 157 | return ct; 158 | } 159 | 160 | 161 | 162 | void HomGate(LWE::CipherText* res, const BinGate gate, const EvalKey& EK, const LWE::CipherText& ct1, const LWE::CipherText& ct2) { 163 | LWE::CipherText e12; 164 | 165 | for (int i = 0; i < n; ++i){ 166 | if (((ct1.a[i] - ct2.a[i]) %q) && ((ct1.a[i] + ct2.a[i]) %q)) 167 | // Ciphertexts are neither equal neither a NOT of each other 168 | break; 169 | if (i==n-1){ 170 | cerr << "ERROR: Please only use independant ciphertexts as inputs." << endl; 171 | exit(1); 172 | } 173 | } 174 | 175 | for (int i = 0; i < n; ++i) 176 | e12.a[i] = (2*q - (ct1.a[i] + ct2.a[i])) % q; 177 | 178 | e12.b = GateConst[gate] - (ct1.b + ct2.b) % q; 179 | 180 | ct_FFT1 ACC; 181 | InitializeACC(ACC, (e12.b + q/4) % q); 182 | for (int i = 0; i < n; ++i) { 183 | int a = (q - e12.a[i] % q) % q; 184 | for (int k = 0; k < BS_exp; ++k, a /= BS_base) { 185 | int a0 = a % BS_base; 186 | if (a0) AddToACC(ACC, *(EK.BSkey[i][a0][k])); 187 | } 188 | } 189 | LWE::CipherTextQN *eQN = MemberTest(t_TestMSB, ACC); 190 | LWE::CipherTextQ eQ; 191 | LWE::KeySwitch(&eQ, EK.KSkey, *eQN); 192 | LWE::ModSwitch(res, eQ); 193 | delete eQN; 194 | } 195 | 196 | void HomNAND(LWE::CipherText* res, const EvalKey& EK, const LWE::CipherText& ct1, const LWE::CipherText& ct2) { 197 | HomGate(res, NAND, EK, ct1, ct2); 198 | } 199 | 200 | void HomNOT(LWE::CipherText* res, const LWE::CipherText& ct) { 201 | for (int i = 0; i < n; ++i) 202 | res->a[i] = (q - ct.a[i]) % q; 203 | res->b = (-ct.b + 5*q/4) % q; 204 | } 205 | 206 | } 207 | -------------------------------------------------------------------------------- /FHEW.h: -------------------------------------------------------------------------------- 1 | #ifndef FHEW_H 2 | #define FHEW_H 3 | 4 | #include "params.h" 5 | #include "LWE.h" 6 | 7 | namespace FHEW { 8 | 9 | typedef Ring_FFT ct_FFT[K2][2]; // Ciphertext in FFT form 10 | typedef ct_FFT* BootstrappingKey[n][BS_base][BS_exp]; 11 | typedef struct { 12 | BootstrappingKey BSkey; 13 | LWE::SwitchingKey KSkey; 14 | } EvalKey; 15 | 16 | void Setup(); 17 | void KeyGen(EvalKey* EK, const LWE::SecretKey LWEsk); 18 | void HomGate(LWE::CipherText* res, const BinGate gate, const EvalKey& EK, const LWE::CipherText& ct1, const LWE::CipherText& ct2); 19 | void HomNAND(LWE::CipherText* res, const EvalKey& EK, const LWE::CipherText& ct1, const LWE::CipherText& ct2); 20 | void HomNOT(LWE::CipherText* res, const LWE::CipherText& ct); 21 | void fwrite_ek(const EvalKey& EK, FILE* f); 22 | EvalKey* fread_ek(FILE* f); 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | COPYRIGHT NOTICE 3 | 4 | FHEW -- A Fully Homomrphic Encryption library 5 | Copyright (C) 2014 Leo Ducas and Daniele Micciancio 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | You can also find the GPL on the GNU web site, http://www.gnu.org/copyleft/gpl.html. 21 | 22 | In addition, we kindly ask you to acknowledge FHEW and its authors 23 | in any program or publication in which you use FHEW. (You are not 24 | required to do so; it is up to your common sense to decide whether 25 | you want to comply with this request or not.) 26 | 27 | This entire copyright notice should be placed in an appropriately 28 | conspicuous place accompanying all distributions of software that 29 | make use of FHEW. 30 | 31 | END COPYRIGHT NOTICE 32 | 33 | 34 | Following is the complete text of the GNU General Public License. 35 | Note that the copyright notice below applies to the text of the license 36 | itself, and not to FHEW. 37 | 38 | 39 | 40 | GNU GENERAL PUBLIC LICENSE 41 | Version 2, June 1991 42 | 43 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 44 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 45 | Everyone is permitted to copy and distribute verbatim copies 46 | of this license document, but changing it is not allowed. 47 | 48 | Preamble 49 | 50 | The licenses for most software are designed to take away your 51 | freedom to share and change it. By contrast, the GNU General Public 52 | License is intended to guarantee your freedom to share and change free 53 | software--to make sure the software is free for all its users. This 54 | General Public License applies to most of the Free Software 55 | Foundation's software and to any other program whose authors commit to 56 | using it. (Some other Free Software Foundation software is covered by 57 | the GNU Library General Public License instead.) You can apply it to 58 | your programs, too. 59 | 60 | When we speak of free software, we are referring to freedom, not 61 | price. Our General Public Licenses are designed to make sure that you 62 | have the freedom to distribute copies of free software (and charge for 63 | this service if you wish), that you receive source code or can get it 64 | if you want it, that you can change the software or use pieces of it 65 | in new free programs; and that you know you can do these things. 66 | 67 | To protect your rights, we need to make restrictions that forbid 68 | anyone to deny you these rights or to ask you to surrender the rights. 69 | These restrictions translate to certain responsibilities for you if you 70 | distribute copies of the software, or if you modify it. 71 | 72 | For example, if you distribute copies of such a program, whether 73 | gratis or for a fee, you must give the recipients all the rights that 74 | you have. You must make sure that they, too, receive or can get the 75 | source code. And you must show them these terms so they know their 76 | rights. 77 | 78 | We protect your rights with two steps: (1) copyright the software, and 79 | (2) offer you this license which gives you legal permission to copy, 80 | distribute and/or modify the software. 81 | 82 | Also, for each author's protection and ours, we want to make certain 83 | that everyone understands that there is no warranty for this free 84 | software. If the software is modified by someone else and passed on, we 85 | want its recipients to know that what they have is not the original, so 86 | that any problems introduced by others will not reflect on the original 87 | authors' reputations. 88 | 89 | Finally, any free program is threatened constantly by software 90 | patents. We wish to avoid the danger that redistributors of a free 91 | program will individually obtain patent licenses, in effect making the 92 | program proprietary. To prevent this, we have made it clear that any 93 | patent must be licensed for everyone's free use or not licensed at all. 94 | 95 | The precise terms and conditions for copying, distribution and 96 | modification follow. 97 | 98 | GNU GENERAL PUBLIC LICENSE 99 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 100 | 101 | 0. This License applies to any program or other work which contains 102 | a notice placed by the copyright holder saying it may be distributed 103 | under the terms of this General Public License. The "Program", below, 104 | refers to any such program or work, and a "work based on the Program" 105 | means either the Program or any derivative work under copyright law: 106 | that is to say, a work containing the Program or a portion of it, 107 | either verbatim or with modifications and/or translated into another 108 | language. (Hereinafter, translation is included without limitation in 109 | the term "modification".) Each licensee is addressed as "you". 110 | 111 | Activities other than copying, distribution and modification are not 112 | covered by this License; they are outside its scope. The act of 113 | running the Program is not restricted, and the output from the Program 114 | is covered only if its contents constitute a work based on the 115 | Program (independent of having been made by running the Program). 116 | Whether that is true depends on what the Program does. 117 | 118 | 1. You may copy and distribute verbatim copies of the Program's 119 | source code as you receive it, in any medium, provided that you 120 | conspicuously and appropriately publish on each copy an appropriate 121 | copyright notice and disclaimer of warranty; keep intact all the 122 | notices that refer to this License and to the absence of any warranty; 123 | and give any other recipients of the Program a copy of this License 124 | along with the Program. 125 | 126 | You may charge a fee for the physical act of transferring a copy, and 127 | you may at your option offer warranty protection in exchange for a fee. 128 | 129 | 2. You may modify your copy or copies of the Program or any portion 130 | of it, thus forming a work based on the Program, and copy and 131 | distribute such modifications or work under the terms of Section 1 132 | above, provided that you also meet all of these conditions: 133 | 134 | a) You must cause the modified files to carry prominent notices 135 | stating that you changed the files and the date of any change. 136 | 137 | b) You must cause any work that you distribute or publish, that in 138 | whole or in part contains or is derived from the Program or any 139 | part thereof, to be licensed as a whole at no charge to all third 140 | parties under the terms of this License. 141 | 142 | c) If the modified program normally reads commands interactively 143 | when run, you must cause it, when started running for such 144 | interactive use in the most ordinary way, to print or display an 145 | announcement including an appropriate copyright notice and a 146 | notice that there is no warranty (or else, saying that you provide 147 | a warranty) and that users may redistribute the program under 148 | these conditions, and telling the user how to view a copy of this 149 | License. (Exception: if the Program itself is interactive but 150 | does not normally print such an announcement, your work based on 151 | the Program is not required to print an announcement.) 152 | 153 | These requirements apply to the modified work as a whole. If 154 | identifiable sections of that work are not derived from the Program, 155 | and can be reasonably considered independent and separate works in 156 | themselves, then this License, and its terms, do not apply to those 157 | sections when you distribute them as separate works. But when you 158 | distribute the same sections as part of a whole which is a work based 159 | on the Program, the distribution of the whole must be on the terms of 160 | this License, whose permissions for other licensees extend to the 161 | entire whole, and thus to each and every part regardless of who wrote it. 162 | 163 | Thus, it is not the intent of this section to claim rights or contest 164 | your rights to work written entirely by you; rather, the intent is to 165 | exercise the right to control the distribution of derivative or 166 | collective works based on the Program. 167 | 168 | In addition, mere aggregation of another work not based on the Program 169 | with the Program (or with a work based on the Program) on a volume of 170 | a storage or distribution medium does not bring the other work under 171 | the scope of this License. 172 | 173 | 3. You may copy and distribute the Program (or a work based on it, 174 | under Section 2) in object code or executable form under the terms of 175 | Sections 1 and 2 above provided that you also do one of the following: 176 | 177 | a) Accompany it with the complete corresponding machine-readable 178 | source code, which must be distributed under the terms of Sections 179 | 1 and 2 above on a medium customarily used for software interchange; or, 180 | 181 | b) Accompany it with a written offer, valid for at least three 182 | years, to give any third party, for a charge no more than your 183 | cost of physically performing source distribution, a complete 184 | machine-readable copy of the corresponding source code, to be 185 | distributed under the terms of Sections 1 and 2 above on a medium 186 | customarily used for software interchange; or, 187 | 188 | c) Accompany it with the information you received as to the offer 189 | to distribute corresponding source code. (This alternative is 190 | allowed only for noncommercial distribution and only if you 191 | received the program in object code or executable form with such 192 | an offer, in accord with Subsection b above.) 193 | 194 | The source code for a work means the preferred form of the work for 195 | making modifications to it. For an executable work, complete source 196 | code means all the source code for all modules it contains, plus any 197 | associated interface definition files, plus the scripts used to 198 | control compilation and installation of the executable. However, as a 199 | special exception, the source code distributed need not include 200 | anything that is normally distributed (in either source or binary 201 | form) with the major components (compiler, kernel, and so on) of the 202 | operating system on which the executable runs, unless that component 203 | itself accompanies the executable. 204 | 205 | If distribution of executable or object code is made by offering 206 | access to copy from a designated place, then offering equivalent 207 | access to copy the source code from the same place counts as 208 | distribution of the source code, even though third parties are not 209 | compelled to copy the source along with the object code. 210 | 211 | 4. You may not copy, modify, sublicense, or distribute the Program 212 | except as expressly provided under this License. Any attempt 213 | otherwise to copy, modify, sublicense or distribute the Program is 214 | void, and will automatically terminate your rights under this License. 215 | However, parties who have received copies, or rights, from you under 216 | this License will not have their licenses terminated so long as such 217 | parties remain in full compliance. 218 | 219 | 5. You are not required to accept this License, since you have not 220 | signed it. However, nothing else grants you permission to modify or 221 | distribute the Program or its derivative works. These actions are 222 | prohibited by law if you do not accept this License. Therefore, by 223 | modifying or distributing the Program (or any work based on the 224 | Program), you indicate your acceptance of this License to do so, and 225 | all its terms and conditions for copying, distributing or modifying 226 | the Program or works based on it. 227 | 228 | 6. Each time you redistribute the Program (or any work based on the 229 | Program), the recipient automatically receives a license from the 230 | original licensor to copy, distribute or modify the Program subject to 231 | these terms and conditions. You may not impose any further 232 | restrictions on the recipients' exercise of the rights granted herein. 233 | You are not responsible for enforcing compliance by third parties to 234 | this License. 235 | 236 | 7. If, as a consequence of a court judgment or allegation of patent 237 | infringement or for any other reason (not limited to patent issues), 238 | conditions are imposed on you (whether by court order, agreement or 239 | otherwise) that contradict the conditions of this License, they do not 240 | excuse you from the conditions of this License. If you cannot 241 | distribute so as to satisfy simultaneously your obligations under this 242 | License and any other pertinent obligations, then as a consequence you 243 | may not distribute the Program at all. For example, if a patent 244 | license would not permit royalty-free redistribution of the Program by 245 | all those who receive copies directly or indirectly through you, then 246 | the only way you could satisfy both it and this License would be to 247 | refrain entirely from distribution of the Program. 248 | 249 | If any portion of this section is held invalid or unenforceable under 250 | any particular circumstance, the balance of the section is intended to 251 | apply and the section as a whole is intended to apply in other 252 | circumstances. 253 | 254 | It is not the purpose of this section to induce you to infringe any 255 | patents or other property right claims or to contest validity of any 256 | such claims; this section has the sole purpose of protecting the 257 | integrity of the free software distribution system, which is 258 | implemented by public license practices. Many people have made 259 | generous contributions to the wide range of software distributed 260 | through that system in reliance on consistent application of that 261 | system; it is up to the author/donor to decide if he or she is willing 262 | to distribute software through any other system and a licensee cannot 263 | impose that choice. 264 | 265 | This section is intended to make thoroughly clear what is believed to 266 | be a consequence of the rest of this License. 267 | 268 | 8. If the distribution and/or use of the Program is restricted in 269 | certain countries either by patents or by copyrighted interfaces, the 270 | original copyright holder who places the Program under this License 271 | may add an explicit geographical distribution limitation excluding 272 | those countries, so that distribution is permitted only in or among 273 | countries not thus excluded. In such case, this License incorporates 274 | the limitation as if written in the body of this License. 275 | 276 | 9. The Free Software Foundation may publish revised and/or new versions 277 | of the General Public License from time to time. Such new versions will 278 | be similar in spirit to the present version, but may differ in detail to 279 | address new problems or concerns. 280 | 281 | Each version is given a distinguishing version number. If the Program 282 | specifies a version number of this License which applies to it and "any 283 | later version", you have the option of following the terms and conditions 284 | either of that version or of any later version published by the Free 285 | Software Foundation. If the Program does not specify a version number of 286 | this License, you may choose any version ever published by the Free Software 287 | Foundation. 288 | 289 | 10. If you wish to incorporate parts of the Program into other free 290 | programs whose distribution conditions are different, write to the author 291 | to ask for permission. For software which is copyrighted by the Free 292 | Software Foundation, write to the Free Software Foundation; we sometimes 293 | make exceptions for this. Our decision will be guided by the two goals 294 | of preserving the free status of all derivatives of our free software and 295 | of promoting the sharing and reuse of software generally. 296 | 297 | NO WARRANTY 298 | 299 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 300 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 301 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 302 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 303 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 304 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 305 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 306 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 307 | REPAIR OR CORRECTION. 308 | 309 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 310 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 311 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 312 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 313 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 314 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 315 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 316 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 317 | POSSIBILITY OF SUCH DAMAGES. 318 | 319 | END OF TERMS AND CONDITIONS 320 | -------------------------------------------------------------------------------- /LWE.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "LWE.h" 4 | #include "params.h" 5 | #include 6 | 7 | using namespace std; 8 | namespace LWE { 9 | 10 | void KeyGen(SecretKey sk) { 11 | KeyGenRestart: 12 | int s=0, ss=0; 13 | for (int i = 0; i < n; ++i) { 14 | 15 | sk[i] = Sample(Chi_Binary); 16 | s+= sk[i]; 17 | ss+= abs(sk[i]); 18 | } 19 | if (abs(s)>5) goto KeyGenRestart; 20 | if (abs(ss - n/2)>5) goto KeyGenRestart; 21 | } 22 | 23 | void KeyGenN(SecretKeyN sk) { 24 | for (int i = 0; i < N; ++i) sk[i] = Sample(Chi1); 25 | } 26 | 27 | void Encrypt(CipherText* ct, const SecretKey sk, int m) { 28 | ct->b = (m % 4) * q / 4; 29 | ct->b += Sample(Chi3); 30 | for (int i = 0; i < n; ++i) { 31 | ct->a[i] = rand() % q; 32 | ct->b = (ct->b + ct->a[i] * sk[i]) % q; 33 | } 34 | } 35 | 36 | int Decrypt(const SecretKey sk, const CipherText& ct) { 37 | int r = ct.b; 38 | for (int i = 0; i < n; ++i) r -= ct.a[i] * sk[i]; 39 | r = ((r % q) + q + q/8) % q; 40 | return 4*r/q; 41 | } 42 | 43 | void DecryptDetail(const SecretKey sk, const CipherText& ct) { 44 | int r = ct.b; 45 | for (int i = 0; i < n; ++i) r -= ct.a[i] * sk[i]; 46 | r = ((r % q) + q + q/8) % q; 47 | int m = 4*r/q; 48 | cerr << "\t Value " << r - q/8 << "\t Decoded as " << m << " * " << q/4 << "\t + " << r - m * q/4 - q/8<< endl; 49 | cout << r - m * q/4 - q/8 << ", "; 50 | } 51 | 52 | 53 | int round_qQ(ZmodQ v) { 54 | return floor(.5 + (double) v * (double) q / (double) Q) + q % q; 55 | } 56 | 57 | void ModSwitch(CipherText* ct, const CipherTextQ& c) { 58 | for (int i = 0; i < n; ++i) 59 | ct->a[i] = round_qQ(c.a[i]); 60 | ct->b = round_qQ(c.b); 61 | } 62 | 63 | void SwitchingKeyGen(SwitchingKey res, const SecretKey new_sk, const SecretKeyN old_sk) { 64 | for (int i = 0; i < N; ++i) 65 | for (int j = 0; j < KS_base; ++j) 66 | for (int k = 0; k < KS_exp; ++k) { 67 | CipherTextQ* ct = new CipherTextQ; 68 | ct->b = -old_sk[i]*j*KS_table[k] + Sample(Chi2); 69 | for (int l = 0; l < n; ++l) { 70 | ct->a[l] = rand(); 71 | ct->b += ct->a[l] * new_sk[l]; 72 | } 73 | res[i][j][k] = ct; 74 | } 75 | } 76 | 77 | void KeySwitch(CipherTextQ* res, const SwitchingKey K, const CipherTextQN& ct) { 78 | for (int k = 0; k < n; ++k) res->a[k] = 0; 79 | res->b = ct.b; 80 | for (int i = 0; i < N; ++i) { 81 | uZmodQ a = -ct.a[i]; 82 | for (int j = 0; j < KS_exp; ++j, a /= KS_base) { 83 | uZmodQ a0 = a % KS_base; 84 | for (int k = 0; k < n; ++k) 85 | res->a[k] -= (K[i][a0][j])->a[k]; 86 | res->b -= (K[i][a0][j])->b; 87 | } 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /LWE.h: -------------------------------------------------------------------------------- 1 | #ifndef LWE_H 2 | #define LWE_H 3 | 4 | #include "params.h" 5 | #include "distrib.h" 6 | 7 | namespace LWE { 8 | 9 | typedef struct { // n-dimensional LWE ciphertext modulo q 10 | int a[n]; // array of n integers modulo q 11 | int b; // integer modulo q 12 | } CipherText; 13 | 14 | typedef struct { // n-dimensional LWE ciphertext modulo Q 15 | ZmodQ a[n]; 16 | ZmodQ b; 17 | } CipherTextQ; 18 | 19 | typedef struct { // N-dimensional LWE ciphertext modulo Q 20 | ZmodQ a[N]; 21 | ZmodQ b; 22 | } CipherTextQN; 23 | 24 | typedef int SecretKey[n]; // n-dimensional LWE secret key 25 | typedef int SecretKeyN[N]; // N-dimensional LWE secret key 26 | 27 | void KeyGen(SecretKey sk); 28 | void KeyGenN(SecretKeyN sk); 29 | void Encrypt(CipherText* ct, const SecretKey sk, int m); 30 | int Decrypt(const SecretKey sk, const CipherText& ct); 31 | 32 | 33 | typedef CipherTextQ* SwitchingKey[N][KS_base][KS_exp]; 34 | // Generate key material (SwitchingKey) required by KeySwitch to transform 35 | // LWE encryptions under old_sk into LWE encryptions under new_sk 36 | void SwitchingKeyGen(SwitchingKey res, const SecretKey new_sk, const SecretKeyN old_sk); 37 | void KeySwitch(CipherTextQ* res, const SwitchingKey K, const CipherTextQN& ct); 38 | 39 | // Changes an LWE ciphertext modulo Q into an LWE ciphertext modulo q 40 | void ModSwitch(CipherText* ct, const CipherTextQ& c); 41 | int round_qQ(ZmodQ v); 42 | 43 | 44 | // For debbugging purpose you can use the following 45 | // void DecryptDetail(const SecretKey sk, const CipherText& ct); 46 | 47 | 48 | } 49 | 50 | 51 | 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX=$(HOME) 2 | CC=g++ 3 | AR=ar 4 | CFLAGS= -ansi -Wall -O3 5 | LDFLAGS= -L. -lfhew -lfftw3 6 | INCLUDE=distrib.h LWE.h FHEW.h FFT.h params.h 7 | 8 | all: libfhew.a cmd fhewTest 9 | 10 | cmd: cmd/gen cmd/enc cmd/nand cmd/dec cmd/gate 11 | 12 | install: $(INCLUDE) libfhew.a 13 | install $(INCLUDE) $(PREFIX)/include 14 | install libfhew.a $(PREFIX)/lib 15 | 16 | uninstall: 17 | rm $(PREFIX)/lib/libfhew.a 18 | rm $(PREFIX)/include/{distrib,LWE,FHEW,FFT,params}.h 19 | 20 | clean: 21 | rm *.o libfhew.a fhewTest cmd/gen cmd/enc cmd/dec cmd/nand cmd/gate || echo nothing to clean 22 | 23 | libfhew.a: distrib.o FFT.o LWE.o FHEW.o 24 | $(AR) -q libfhew.a distrib.o FFT.o LWE.o FHEW.o 25 | 26 | distrib.o: distrib.cpp distrib.h params.h 27 | $(CC) $(CFLAGS) -c distrib.cpp 28 | 29 | FFT.o: FFT.h FFT.cpp params.h FHEW.h 30 | $(CC) $(CFLAGS) -c FFT.cpp 31 | 32 | LWE.o: LWE.h LWE.cpp FFT.h params.h distrib.h 33 | $(CC) $(CFLAGS) -c LWE.cpp 34 | 35 | FHEW.o: FHEW.h FHEW.cpp FFT.h LWE.h params.h 36 | $(CC) $(CFLAGS) -c FHEW.cpp 37 | 38 | fhewTest: fhewTest.cpp libfhew.a 39 | $(CC) $(CFLAGS) -o fhewTest fhewTest.cpp $(LDFLAGS) 40 | 41 | common.o: cmd/common.cpp cmd/common.h libfhew.a 42 | $(CC) $(CFLAGS) -c cmd/common.cpp 43 | 44 | cmd/gen: cmd/gen.cpp common.o libfhew.a 45 | $(CC) $(CFLAGS) -o cmd/gen cmd/gen.cpp common.o $(LDFLAGS) 46 | 47 | cmd/enc: cmd/enc.cpp common.o libfhew.a 48 | $(CC) $(CFLAGS) -o cmd/enc cmd/enc.cpp common.o $(LDFLAGS) 49 | 50 | cmd/nand: cmd/nand.cpp common.o libfhew.a 51 | $(CC) $(CFLAGS) -o cmd/nand cmd/nand.cpp common.o $(LDFLAGS) 52 | 53 | cmd/gate: cmd/gate.cpp common.o libfhew.a 54 | $(CC) $(CFLAGS) -o cmd/gate cmd/gate.cpp common.o $(LDFLAGS) 55 | 56 | cmd/dec: cmd/dec.cpp common.o libfhew.a 57 | $(CC) $(CFLAGS) -o cmd/dec cmd/dec.cpp common.o $(LDFLAGS) 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FHEW 2 | 3 | ## A Fully Homomorphic Encryption library 4 | 5 | **version 2.0-alpha** -- *Release date: 2017.05.30* 6 | 7 | **Updates** 8 | - Made Homomorphic gate computation 6x faster, by noticing that it is sufficient to compute ACC[1]. This trick is somehow equivalent to the external product from [this paper](http://eprint.iacr.org/2016/870) 9 | - Implemented support for more gates: AND, OR, NAND, NOR, NOT 10 | - Forbids operation on non-independant ciphertext: (x OP x) or (x OP (not x)) 11 | - Bugfixes 12 | 13 | **Authors:** Leo Ducas and Daniele Micciancio 14 | 15 | FHEW is open-source software distributed under the terms of the GNU 16 | General Public License. See the file LICENSE for complete details on the licensing of FHEW. 17 | The FHEW library is based on the Fully Homorphic Encryption scheme 18 | described in the paper ["FHE bootstrapping in less than a second"](http://eprint.iacr.org/2014/816) 19 | (L. Ducas and D. Micciancio, Cryptology ePrint Archive 2014/816,) 20 | and makes use of the [FFTW](http://www.fftw.org) library (the "Fastest 21 | Fourier Transform in the West"). Hence the name FHEW, which you may 22 | read as the "Fastest Homomorphic Encryption in the West", though the 23 | name is more of a reference to FFTW than a claim about performance. The 24 | library provides a symmetric encryption scheme to encrypt (and 25 | decrypt) single bit messages, supporting the homomorphic evaluation of 26 | arbitrary boolean circuits on encrypted data using a public (evaluation) key. 27 | 28 | **Note** Please do not expect maintenance of this code. 29 | 30 | ### Requirements 31 | 32 | FHEW requires the FFTW 3 library available at , 33 | and a c++ compiler. The library is written primarily in C, but a C++ 34 | compiler is needed to support a few syntactical extensions (like 35 | namespaces and reference parameters) used to improve the readibility 36 | of the code. Editing the library so to require just a c compiler 37 | should be straightforward. The library has been tested using the g++ 38 | compiler from the [GNU compiler collection](http://gcc.gnu.org) (gcc 39 | version 4.9.1), but should work fine with other compilers as well. 40 | 41 | ### Installation 42 | 43 | To build the library, just run ```make```. This will produce a 44 | library (libfhew.a), and a number of test/example programs. (See 45 | below.) You can also run ``` make install``` to install the header 46 | files and fhew library required to compile your own programs making 47 | use of FHEW. By default, these are installed in $(HOME)/include and 48 | $(HOME)/lib. Edit the Makefile to fit your needs. 49 | 50 | You can test the library by running the test program ```fhewTest```. 51 | Running the test program with no arguments prints a simple usage message. 52 | 53 | ### Command Line Usage 54 | 55 | FHEW is a library and was not designed to be used directly from the 56 | command line, but we do provide a command line interface for testing purposes. 57 | The *cmd* subfolder contains four programs: *gen*, *enc*, *nand* and 58 | *dec* for key generation, encryption, homorphic computation and 59 | decryption. Running each command with no arguments prints out a simple 60 | usage message. The commands can be used as follows: 61 | 62 | ``` 63 | gen sec.key ev.key 64 | enc 0 sec.key a.ct 65 | enc 1 sec.key b.ct 66 | gate nand ev.key a.ct b.ct c.ct 67 | dec sec.key c.ct 68 | ``` 69 | This generates a secret key and corresponding evaluation key, which 70 | are stored in the files sec.key and ev.key. 71 | The secret key is then used to encrypt the message 0 and the message 72 | 1, storing the ciphertexts in a.ct and b.ct. 73 | The homomorphic NAND of the two ciphertexts is computed using the 74 | evaluation key. Finally, the resulting ciphertext stored in c.ct is decrypted. 75 | The output of the last command should be 1. 76 | 77 | ### Library Interface 78 | 79 | ```c++ 80 | void FHEW::Setup(); 81 | ``` 82 | Should be run once (and only once) before any other function is used. 83 | 84 | ```c++ 85 | void LWE::KeyGen(LWE::SecretKey sk); 86 | ``` 87 | Generate an LWE secret key. 88 | (Note: please initialize your randomness with srand()) 89 | 90 | ```c++ 91 | void LWE::Encrypt(LWE::CipherText* ct, const LWE::SecretKey sk, int m); 92 | ``` 93 | Encrypt a message. 94 | (Note: please initialize your randomness with srand()) 95 | 96 | ```c++ 97 | int LWE::Decrypt(const LWE::SecretKey sk, const LWE::CipherText& ct); 98 | ``` 99 | Decrypt a ciphertext. 100 | 101 | ```c++ 102 | void FHEW::KeyGen(FHEW::EvalKey* EK, const LWE::SecretKey sk); 103 | ``` 104 | Generate an Evaluation Key from a secret key. 105 | (Note: please initialize your randomness with srand()) 106 | 107 | ```c++ 108 | void FHEW::HomNAND(LWE::CipherText* res, const FHEW::EvalKey& EK, 109 | const LWE::CipherText& ct1, const LWE::CipherText& ct2); 110 | ``` 111 | Perform a homomorphic NAND operation. Deprecated due to the more general function below. 112 | 113 | ```c++ 114 | void HomGate(LWE::CipherText* res, const BinGate gate, const EvalKey& EK, 115 | const LWE::CipherText& ct1, const LWE::CipherText& ct2); 116 | ``` 117 | Perform a homomorphic OP operation where OP={OR,AND,NOR,NAND}. 118 | 119 | ```c++ 120 | void HomNOT(LWE::CipherText* res, const LWE::CipherText& ct); 121 | ``` 122 | Perform a homomorphic NOT operation. 123 | (note: does not require any key material). 124 | 125 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 2 | This library was develop quickly as a demonstration of feasibility 3 | of the cryptosystem presented in the article 4 | 5 | FHE Bootstrapping in less than a second, 6 | by Léo Ducas and Daniele Micciancio, 7 | avaliable at https://eprint.iacr.org/2014/816. 8 | 9 | We recall (complete statement should be found in the file LICENSE) that: 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | 17 | Here is a non-exhaustive list of improvement that could be added 18 | - Support for other operation than NAND 19 | - Usage of NTT rather than complex FFT. 20 | - Vectorialization of linear algebra operations. 21 | 22 | Here is a non exhaustive list of NECESSARY modification for any use 23 | of this library beyond scientific curiosity 24 | - Replace calls to Rand() by cryptographic pseudo-randomness. 25 | -------------------------------------------------------------------------------- /cmd/common.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../LWE.h" 4 | #include "../FHEW.h" 5 | #include 6 | 7 | using namespace std; 8 | 9 | 10 | void SaveSecretKey(const LWE::SecretKey* LWEsk, char* filepath) { 11 | FILE * f; 12 | f = fopen(filepath, "wb"); // wb -write binary 13 | if (f == NULL) { 14 | cerr << "Failed to open "<< filepath << " in Write-Binary mode .\n"; 15 | exit(1); 16 | } 17 | cerr << "Writing Secret key to "<< filepath << ".\n"; 18 | fwrite(LWEsk, sizeof(LWE::SecretKey), 1, f); 19 | fclose(f); 20 | } 21 | 22 | LWE::SecretKey* LoadSecretKey(char* filepath) { 23 | FILE * f; 24 | f = fopen(filepath, "rb"); // wb -write binary 25 | if (f == NULL) { 26 | cerr << "Failed to open "<< filepath << " in Read-Binary mode .\n"; 27 | exit(1); 28 | } 29 | LWE::SecretKey* LWEsk = (LWE::SecretKey*) malloc(sizeof(LWE::SecretKey)); 30 | cerr << "Reading Secret key From "<< filepath << ".\n"; 31 | assert(fread(LWEsk, sizeof(LWE::SecretKey), 1, f)); 32 | cerr << "Secret Key read.\n"; 33 | fclose(f); 34 | return LWEsk; 35 | } 36 | 37 | 38 | 39 | 40 | 41 | void SaveEvalKey(const FHEW::EvalKey *EK, char* filepath) { 42 | FILE * f; 43 | f = fopen(filepath, "wb"); // wb -write binary 44 | if (f == NULL) { 45 | cerr << "Failed to open "<< filepath << " in Write-Binary mode .\n"; 46 | exit(1); 47 | } 48 | cerr << "Writing Evaluation key to "<< filepath << ".\n"; 49 | FHEW::fwrite_ek(*EK, f); 50 | fclose(f); 51 | } 52 | 53 | FHEW::EvalKey* LoadEvalKey(char* filepath) { 54 | FHEW::EvalKey* EK; 55 | FILE * f; 56 | f = fopen(filepath, "rb"); // rb -read binary 57 | if (f == NULL){ 58 | cerr << "Failed to open "<< filepath << " in Read-Binary mode .\n"; 59 | exit(1); 60 | } 61 | cerr << "Reading Evaluation key from "<< filepath << ".\n"; 62 | EK = FHEW::fread_ek(f); 63 | cerr << "KSKey Read : " << N << "\t" << KS_base << "\t" << KS_exp << " .\n"; 64 | fclose(f); 65 | return EK; 66 | } 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | void SaveCipherText(const LWE::CipherText* ct, char* filepath){ 75 | FILE * f; 76 | f = fopen(filepath, "wb"); // wb -write binary 77 | if (f == NULL){ 78 | cerr << "Failed to open "<< filepath << " in Write-Binary mode .\n"; 79 | exit(1); 80 | } 81 | cerr << "Writing CipherText to "<< filepath << ".\n"; 82 | assert(fwrite(ct, sizeof(LWE::CipherText), 1, f)); 83 | fclose(f); 84 | } 85 | 86 | LWE::CipherText* LoadCipherText(char* filepath) { 87 | FILE * f; 88 | f = fopen(filepath, "rb"); // wb -write binary 89 | if (f == NULL) { 90 | cerr << "Failed to open "<< filepath << " in Read-Binary mode.\n"; 91 | exit(1); 92 | } 93 | cerr << "Loading CipherText from "<< filepath << ".\n"; 94 | LWE::CipherText* ct = new LWE::CipherText; 95 | assert(fread(ct, sizeof(LWE::CipherText), 1, f)); 96 | fclose(f); 97 | return ct; 98 | } -------------------------------------------------------------------------------- /cmd/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | 5 | #include 6 | #include 7 | #include "../LWE.h" 8 | #include "../FHEW.h" 9 | #include 10 | 11 | using namespace std; 12 | 13 | 14 | void SaveSecretKey(const LWE::SecretKey* ct, char* filepath); 15 | LWE::SecretKey* LoadSecretKey(char* filepath); 16 | 17 | 18 | void SaveEvalKey(const FHEW::EvalKey *EK, char* filepath); 19 | FHEW::EvalKey* LoadEvalKey(char* filepath); 20 | 21 | 22 | void SaveCipherText(const LWE::CipherText* ct, char* filepath); 23 | LWE::CipherText* LoadCipherText(char* filepath); 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /cmd/dec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../FHEW.h" 4 | #include "../LWE.h" 5 | #include "common.h" 6 | #include 7 | 8 | using namespace std; 9 | 10 | 11 | void help(char* cmd) { 12 | cerr << "\nusage: " << cmd << " SecretKeyFileName CipherTextFileName \n\n" 13 | << " Decrypt the CipherText under some SecretKey and print it on the std output.\n\n"; 14 | exit(0); 15 | } 16 | 17 | 18 | int main(int argc, char *argv[]) { 19 | if (argc != 3) help(argv[0]); 20 | char* sk_fn = argv[1]; 21 | char* ct_fn = argv[2]; 22 | 23 | FHEW::Setup(); 24 | 25 | 26 | LWE::SecretKey* SK = LoadSecretKey(sk_fn); 27 | LWE::CipherText* ct = LoadCipherText(ct_fn); 28 | int m = LWE::Decrypt(*SK,*ct); 29 | cout << m << "\n"; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /cmd/enc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../LWE.h" 4 | #include "../FHEW.h" 5 | #include "common.h" 6 | #include 7 | 8 | using namespace std; 9 | 10 | void help(char* cmd) { 11 | cerr << "\nusage: " << cmd << " Message SecretKeyFileName CipherTextFileName \n\n" 12 | << " Encrypt the Message under some SecretKey and store it in a File.\n\n"; 13 | exit(0); 14 | } 15 | 16 | 17 | int main(int argc, char *argv[]) { 18 | srand(time(NULL)); 19 | if (argc != 4) help(argv[0]); 20 | int message = atoi(argv[1]); 21 | char* sk_fn = argv[2]; 22 | char* ct_fn = argv[3]; 23 | 24 | if (!((message ==0)||(message ==1))){ 25 | cerr << " The message must be 0 or 1.\n"; 26 | exit(0); 27 | } 28 | 29 | LWE::SecretKey* SK = LoadSecretKey(sk_fn); 30 | 31 | LWE::CipherText ct; 32 | LWE::Encrypt(&ct, *SK, message); SaveCipherText(&ct,ct_fn); 33 | } 34 | -------------------------------------------------------------------------------- /cmd/gate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../FHEW.h" 4 | #include "common.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | FHEW::EvalKey* EK; 13 | 14 | 15 | void help(char* cmd) { 16 | cerr << "\nusage: " << cmd << " Gate EvalKeyFileName InCTFileName1 InCTFileName2 OutCTFileName \n\n" 17 | << " Perform Homomorphic Gate computation where Gate={AND, OR, NAND, NOR}\n\n"; 18 | exit(0); 19 | } 20 | 21 | 22 | int main(int argc, char *argv[]) { 23 | if (argc != 6) help(argv[0]); 24 | string gate_n = argv[1]; 25 | char* ek_fn = argv[2]; 26 | char* ict1_fn = argv[3]; 27 | char* ict2_fn = argv[4]; 28 | char* oct_fn = argv[5]; 29 | 30 | BinGate gate; 31 | if (gate_n=="OR") gate = OR; 32 | else if (gate_n=="AND") gate = AND; 33 | else if (gate_n=="NOR") gate = NOR; 34 | else if (gate_n=="NAND") gate = NAND; 35 | else 36 | { 37 | cerr << "\n This gate does not exists (please choose {AND, OR, NAND, NOR}) \n"; 38 | exit(1); 39 | } 40 | 41 | 42 | 43 | FHEW::Setup(); 44 | 45 | EK = LoadEvalKey(ek_fn); 46 | 47 | LWE::CipherText *ct1,*ct2,*ct3; 48 | 49 | ct1 = LoadCipherText(ict1_fn); 50 | ct2 = LoadCipherText(ict2_fn); 51 | ct3 = new LWE::CipherText; 52 | 53 | 54 | FHEW::HomGate(ct3, gate, *EK,*ct1,*ct2); 55 | 56 | SaveCipherText(ct3,oct_fn); 57 | } 58 | -------------------------------------------------------------------------------- /cmd/gen.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../LWE.h" 4 | #include "../FHEW.h" 5 | #include "common.h" 6 | #include "../distrib.h" 7 | #include 8 | 9 | using namespace std; 10 | 11 | FHEW::EvalKey EK; 12 | LWE::SecretKey LWEsk; 13 | 14 | 15 | void help(char* cmd) { 16 | cerr << "\nusage: " << cmd << " SecretKeyFileName EvalKeyFileName \n\n" 17 | << " Generate a secret key sk and evaluation key ek, and store them in two separate files.\n\n"; 18 | exit(0); 19 | } 20 | 21 | 22 | int main(int argc, char *argv[]) { 23 | srand(time(NULL)); 24 | if (argc != 3) help(argv[0]); 25 | char* sk_fn = argv[1]; 26 | char* ek_fn = argv[2]; 27 | 28 | FHEW::Setup(); 29 | LWE::KeyGen(LWEsk); 30 | FHEW::KeyGen(&EK, LWEsk); 31 | SaveEvalKey(&EK,ek_fn); 32 | SaveSecretKey(&LWEsk,sk_fn); 33 | } 34 | -------------------------------------------------------------------------------- /cmd/nand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../FHEW.h" 4 | #include "common.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | FHEW::EvalKey* EK; 13 | 14 | 15 | void help(char* cmd) { 16 | cerr << "\nusage: " << cmd << " EvalKeyFileName InCTFileName1 InCTFileName2 OutCTFileName \n\n" 17 | << " Perform Homomorphic NAND computation.\n\n"; 18 | exit(0); 19 | } 20 | 21 | 22 | int main(int argc, char *argv[]) { 23 | if (argc != 5) help(argv[0]); 24 | char* ek_fn = argv[1]; 25 | char* ict1_fn = argv[2]; 26 | char* ict2_fn = argv[3]; 27 | char* oct_fn = argv[4]; 28 | 29 | FHEW::Setup(); 30 | 31 | EK = LoadEvalKey(ek_fn); 32 | 33 | LWE::CipherText *ct1,*ct2,*ct3; 34 | 35 | ct1 = LoadCipherText(ict1_fn); 36 | ct2 = LoadCipherText(ict2_fn); 37 | ct3 = new LWE::CipherText; 38 | 39 | FHEW::HomNAND(ct3, *EK,*ct1,*ct2); 40 | 41 | SaveCipherText(ct3,oct_fn); 42 | } 43 | -------------------------------------------------------------------------------- /distrib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "distrib.h" 3 | #include 4 | #include 5 | 6 | int Sample(const Distrib& Chi) { 7 | if (Chi.max) { 8 | double r = static_cast (rand()) / static_cast (RAND_MAX); 9 | for (int i = 0; i < Chi.max; ++i) 10 | if (r<= Chi.table[i]) return i - Chi.offset; 11 | std::cerr << "Sampling Error: distribution table ending before (double) 1.0" << std::endl; 12 | exit(1); 13 | } 14 | 15 | double r, s = Chi.std_dev; 16 | if (s < 500){ 17 | int x, maxx = ceil(s*8); 18 | while(true) { 19 | x = rand() % (2*maxx + 1) - maxx; 20 | r = static_cast (rand()) / static_cast (RAND_MAX); 21 | if (r < exp(- x*x / (2*s*s))) return x; 22 | } 23 | } 24 | 25 | // For some reason unknown to us, the previous implementation provides a bad distribution for large s... 26 | // We switch from "discrete gaussian" to rounded gaussian when s gets larger 27 | 28 | double x; 29 | 30 | while(true) { 31 | x = static_cast (rand()) / static_cast (RAND_MAX); 32 | x = 16 *x -8; 33 | r = static_cast (rand()) / static_cast (RAND_MAX); 34 | if (r < exp(- x*x / 2 )) return floor(.5 + x*s) ; 35 | } 36 | 37 | 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /distrib.h: -------------------------------------------------------------------------------- 1 | #ifndef DISTRIB_H 2 | #define DISTRIB_H 3 | 4 | #include "params.h" 5 | 6 | typedef struct { 7 | double std_dev; 8 | int max; // Size of table. Set to 0 to ignore table and use rejection sampling 9 | int offset; 10 | const float* table; // CDF of Gaussian of standard deviation std_dev centered around offset 11 | } Distrib; 12 | 13 | int Sample(const Distrib& Chi); /* sample integer with gaussian distribution */ 14 | 15 | // Distribution of std dev 1.2 16 | const float Chi1_Table[23] = { 17 | 1.12011750313263e-14, 2.38717233762211e-12, 3.04966971020178e-10, 18 | 2.34394541319773e-8, 1.08538196465647e-6, 0.0000303513786306856, 19 | 0.000514575939439740, 0.00532464699317562, 0.0340111330223921, 20 | 0.136723892128727, 0.357520614142345, 0.642479385857655, 21 | 0.863276107871273, 0.965988866977608, 0.994675353006824, 22 | 0.999485424060560, 0.999969648621369, 0.999998914618035, 23 | 0.999999976560546, 0.999999999695033, 0.999999999997613, 24 | 0.999999999999989, 1.00000000000000}; 25 | 26 | const Distrib Chi1 = { 27 | 1.4, 28 | 23, 29 | 11, 30 | Chi1_Table 31 | }; 32 | 33 | const float NoTable[1] = {1}; 34 | 35 | const Distrib Chi2 = { 36 | (double) (1 << 17), 37 | 0, 38 | 0, 39 | NoTable 40 | 41 | }; 42 | 43 | const Distrib Chi3 = { 44 | (double) 6, 45 | 0, 46 | 0, 47 | NoTable 48 | 49 | }; 50 | 51 | const float Binary_Table[3] = { 52 | .25, 53 | .75, 54 | 1.0 }; 55 | 56 | 57 | const Distrib Chi_Binary = { 58 | 0, 59 | 3, 60 | 1, 61 | Binary_Table 62 | }; 63 | 64 | 65 | 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /fhewTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "LWE.h" 4 | #include "FHEW.h" 5 | #include "distrib.h" 6 | 7 | using namespace std; 8 | 9 | void help(char* cmd) { 10 | cerr << "\nusage: " << cmd << " n\n\n" 11 | << " Generate a secret key sk and evaluation key ek, and repeat the following test n times:\n" 12 | << " - generate random bits b1,b2,b3,b4\n" 13 | << " - compute ciphertexts c1, c2, c3 and c4 encrypting b1, b2, b3 and b4 under sk\n" 14 | << " - homomorphically compute the encrypted (c1 NAND c2) NAND (c3 NAND c4) \n" 15 | << " - decrypt all the intermediate results and check correctness \n" 16 | << "\n If any of the tests fails, print ERROR and stop immediately.\n\n"; 17 | exit(0); 18 | } 19 | 20 | int cleartext_gate(int v1, int v2, BinGate gate){ 21 | switch(gate) 22 | { 23 | case OR: return v1 || v2; 24 | case AND: return v1 && v2; 25 | case NOR: return not(v1 || v2); 26 | case NAND: return not(v1 && v2); 27 | default: cerr << "\n This gate does not exists \n"; exit(1); return 0; 28 | } 29 | } 30 | 31 | void cerr_gate(BinGate gate){ 32 | switch(gate) 33 | { 34 | case OR: cerr << " OR\t"; return; 35 | case AND: cerr << " AND\t"; return; 36 | case NOR: cerr << " NOR\t"; return; 37 | case NAND: cerr << " NAND\t"; return; 38 | } 39 | } 40 | 41 | 42 | int main(int argc, char *argv[]) { 43 | if (argc != 2) help(argv[0]); 44 | int count = atoi(argv[1]); 45 | 46 | cerr << "Setting up FHEW \n"; 47 | FHEW::Setup(); 48 | cerr << "Generating secret key ... "; 49 | LWE::SecretKey LWEsk; 50 | LWE::KeyGen(LWEsk); 51 | cerr << " Done.\n"; 52 | cerr << "Generating evaluation key ... this may take a while ... "; 53 | FHEW::EvalKey EK; 54 | FHEW::KeyGen(&EK, LWEsk); 55 | cerr << " Done.\n\n"; 56 | cerr << "Testing depth-2 homomorphic circuits " << count << " times.\n"; 57 | cerr << "Circuit shape : (a GATE NOT(b)) GATE (c GATE d)\n\n"; 58 | 59 | int v1,v2,sv1 = 2,sv2 = 2; 60 | LWE::CipherText se1, se2, e1, e2, e12; 61 | 62 | for (int i = 1; i <= 3*count; ++i) { 63 | 64 | if (i % 3){ 65 | v1 = rand()%2; 66 | v2 = rand()%2; 67 | LWE::Encrypt(&e1, LWEsk, v1); 68 | LWE::Encrypt(&e2, LWEsk, v2); 69 | if (i%3 == 1){ 70 | cerr << " NOT\tEnc(" << v2 << ") = "; 71 | FHEW::HomNOT(&e2, e2); 72 | int notv2 = LWE::Decrypt(LWEsk, e2); 73 | cerr << "Enc(" << notv2 << ")" << endl; 74 | if (not (notv2 == not(v2))){ 75 | cerr << "\n ERROR: incorrect NOT Homomorphic computation at iteration " << i+1 << "\n"; 76 | exit(1); 77 | } 78 | v2 = not v2; 79 | } 80 | } 81 | else { 82 | v1 = sv1; 83 | v2 = sv2; 84 | e1 = se1; 85 | e2 = se2; 86 | } 87 | 88 | BinGate gate = static_cast(rand()%4); 89 | 90 | cerr << "Enc(" << v1 << ")"; 91 | cerr_gate(gate); 92 | cerr << "Enc(" << v2 << ") = "; 93 | 94 | FHEW::HomGate(&e12, gate, EK, e1, e2); 95 | int v12 = LWE::Decrypt(LWEsk, e12); 96 | 97 | cerr << "Enc(" << v12 << ")"; 98 | cerr << endl; 99 | 100 | if (i % 3 == 1){ 101 | sv1 = v12; 102 | se1 = e12; 103 | } 104 | if (i % 3 == 2){ 105 | sv2 = v12; 106 | se2 = e12; 107 | } 108 | if (i % 3 == 0) 109 | cerr << endl; 110 | 111 | if (cleartext_gate(v1, v2, gate) != v12) 112 | { cerr << "\n ERROR: incorrect Homomorphic Gate computation at iteration " << i+1 << "\n"; 113 | exit(1); 114 | } 115 | } 116 | 117 | cerr << "\nPassed all tests!\n\n"; 118 | } 119 | 120 | 121 | -------------------------------------------------------------------------------- /params.h: -------------------------------------------------------------------------------- 1 | #ifndef PARAM_H 2 | #define PARAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | const int n = 500; 10 | 11 | const int N = 1024; 12 | const int N2 = N/2+1; 13 | 14 | const int K = 3; 15 | const int K2 = 6; 16 | 17 | const long int Q = (long int) 1 << 32; 18 | const int q = 512; 19 | const int q2 = 256; 20 | 21 | typedef int32_t ZmodQ; 22 | typedef uint32_t uZmodQ; 23 | const ZmodQ v = (1 << 29) +1; // Q/8 +1 24 | const ZmodQ v_inverse = 3758096385; // 1/v mod Q 25 | 26 | const ZmodQ vgprime[3] = {v, v<<11, v<<22}; 27 | const int g_bits[3] = {11, 11, 10}; 28 | const int g_bits_32[3] = {21, 21, 22}; 29 | 30 | 31 | const int KS_base = 25; 32 | const int KS_exp = 7; 33 | const ZmodQ KS_table[7] = {1, 34 | 25, 35 | 25*25, 36 | 25*25*25, 37 | 25*25*25*25, 38 | 25*25*25*25*25, 39 | 25*25*25*25*25*25}; 40 | 41 | const int BS_base = 23; 42 | const int BS_exp = 2; 43 | const int BS_table[2] = {1,23}; 44 | 45 | typedef ZmodQ Ring_ModQ[N]; 46 | typedef fftw_complex Ring_FFT[N2]; 47 | 48 | enum BinGate {OR, AND , NOR, NAND}; 49 | const int GateConst[4] = {15*q/8, 9*q/8, 11*q/8, 13*q/8}; 50 | 51 | 52 | #endif 53 | --------------------------------------------------------------------------------