# An Efficient BGV-type Encryption Scheme for IoT Systems
## Appendix A Source Code of Our Implementation
### stdafx.h
#### #pragma once
;i++)  {  dct.d0[i]=ct1.c0[i]*ct2.c0[i];  dct.d0[i]=mod(dct.d0[i],pp.q[dct.depth]);  dct.d1[i]=ct1.c0[i]*ct2.c1[i]+ct1.c1[i]*ct2.c0[i];  dct.d1[i]=mod(dct.d1[i],pp.q[dct.depth]);  dct.d2[i]=-ct1.c1[i]*ct2.c1[i];  dct.d2[i]=-mod(dct.d2[i],pp.q[dct.depth]);  }  //printf(\"the depth after CL is %d\
\",dct.depth);  return dct; } Ciphertext& SwitchKey(PubPara pp, PubKey epk, DCiphertext dct) {  Ciphertext ct;ct.depth=dct.depth; for(int i=0;i<l;ii++) {  ct.c0[i]=dct.d0[i]*pp.p[ct.depth]+dct.d2[i]*epk.b[i];  ct.c0[i]=mod(ct.c0[i],pp.q[ct.depth]);  ct.c1[i]=dct.d1[i]*pp.p[ct.depth]+dct.d2[i]*epk.a[i];  ct.c1[i]=mod(ct.c1[i],pp.q[ct.depth]);  } //Ciphertext rect = SwitchModulus(pp, ct);  return ct; } PubPara& Setup(int p) {  PubPara pp;  pp.p[0]=p;  pp.q[0]=pp.p[0];  pp.rp[0]=1;  printf(\"p[0]:%d\tq[0]%d\trp[0]:%d\
\",pp.p[0],pp.q[0],pp.rp[0]);  for(int i=0;i<L-1;i++) {  pp.p[i+1]=proper_prime(pp.p[0],pp.p[i]+1);  pp.q[i+1]=pp.p[i+1]*pp.q[i];  pp.rp[i]=mod_reverse(pp.p[i+1],pp.q[i]);  printf(\"p[%d]:%d\tq[%d]%d\trp[%d]:%d\
\",(i+1),pp.p[i+1],(i+1),pp.q[i+1],(i),pp.rp[i]);  }  return pp; } SecKey& SecKeyGen(PubPara pp) {  srand(1);  SecKey sk; for(int i=0;i<l;ii++) {  sk.s[i]=rand()%pp.q[L-1];  } /*  printf(\"sk:(\");  for(int i=0;j<lj++) {  printf(\"%d\",sk.s[j]);  if(j!=l-1)printf(\",\");  }  printf(\")\
\");  */  return sk; }  PubKey& EncryptionPubKeyGen(PubPara pp, SecKey sk) {  srand(2);  PubKey pk;unsigned long eps[l]; for(int i=0;i<l;i++) {  pk.a[i]=mod(rand(),pp.q[L-1]);  eps[i]=mod(rand(),err);  pk.b[i]=pk.a[i]*sk.s[i]+pp.p[0]*eps[i];  pk.b[i]=mod(pk.b[i],pp.q[L-1]);  }  printf(\" pk a:(\");  for(int j=0j<lj++) {  printf(\"%d\",pk.a[j]);  if(j!=l-1)printf(\",\");  }  printf(\"),\tb:(\");  for(int j=0j<lj++)  {  printf(\"%d\",pk.b[j]);  if(j!=l-1)printf(\",\");  }  printf(\")\
\");  return pk; } ```
PubKey& SwitchKeyGen(PubPara pp, SecKey sk) {  
srand(3);  PubKey pk;  unsigned long eps[l];  for(int i=0;i<l;i++) {  
pk.a[i]=mod(rand(),pp.q[L-1]);  eps[i]=mod(rand(),err);  int rnd = rand()%err; //rnd cannot be too much, otherwise b will exceed the representation range of int and decrypt will fail  
pk.b[i]=pk.a[i]*sk.s[i]+pp.p[0]*eps[i]-sk.s[i]*sk.s[i]*(rnd *pp.p[0]+1);  pk.b[i]=mod(pk.b[i],pp.q[L-1]);  }  printf(\"epk: a:(\");  for(int j=0j<lj++) {  printf(\"%d\",pk.a[j]);  if(j!=l-1)printf(\",\");  }  printf(\")\
\");return pk; } Ciphertext& Encrypt(PubPara pp, PubKey pk, Plaintext pt, int depth) {  rsrand(3);  int v[l], e0[l], e1[l];  Ciphertext ct;  for(int i=0;i<l;i++) {  v[i]=rand()%2;  e0[i]=rand()%err;  e1[i]=rand()%err;  ct.c0[i]=pk.b[i]*v[i] + pp.p[0]*e0[i]+pt.m[i];  ct.c0[i]=mod(ct.c0[i]pp.q[depth]);  ct.c1[i]=pk.a[i]*v[i] + pp.p[0]*e1[i];  ct.c1[i]=mod(ct.c1[i],pp.q[depth]); }  ct.depth=depth;  return ct; } } Plaintext& Decrypt(PubPara pp, SecKey sk, Ciphertext ct) {  Plaintext pt;  for(int i=0;i<l;i++) {  pt.m[i] = ct.c0[i] - sk.s[i]*ct.c1[i];  pt.m[i] = mod(pt.m[i],pp.q[ct.depth]);  pt.m[i] = mod(pt.m[i],pp.p[0]); }  printf(\"(\");  for(int j=0j<lj++) {  printf(\"%d\",pt.m[j]);  if(j!=1-1)printf(\",\"); }  printf(\")\
\");  return pt; } Ciphertext& add(PubPara pp, Ciphertext ct1, Ciphertext ct2) { //printf(\"in add\
\");  Ciphertext ct;  if(ct1.depth!=ct2.depth) {  printf(\"the depth of the two cts are not equal\");  return ct; }  ct.depth=ct1.depth; for(int i=0;i<l;i++)ct.c0[i] = ct1.c0[i] + ct2.c0[i];  ct.c0[i] = mod(ct.c0[i],pp.q[ct.depth]);  ct.c1[i] = ct1.c1[i] + ct2.c1[i];  ct.c1[i] = mod(ct.c1[i],pp.q[ct.depth]);  ]  return ct; } Ciphertext& mul(PubPara pp, PubKey epk, Ciphertext ct1, Ciphertext ct2) {  //printf(\"in mul\
\");  int depth1 = ct1.depth;  int depth2 = ct2.depth;  //printf(\"ct1 depth:%d,ct2 depth:%d\
\",depth1,depth2);  Ciphertext s_ctl1_s_ct2;  if(depth1 == depth2)  {  s_ctl = SwitchModulus(pp,ct1);  s_ct2 = SwitchModulus(pp,ct2);  }  else if(depth1 <depth2)  {  s_ctl = SwitchModulus(pp,ct1);  s_ct2 = SwitchModulus(pp,ct2,depth1-1);  }  else {  s_ctl = SwitchModulus(pp,ct1,depth2-1);  s_ct2 = SwitchModulus(pp,ct2);  } DCiphertext dct = CTLinearization(pp,s_ctl,s_ct2);  Ciphertext mct = SwitchKey(pp,epk,dct);  return mct; } Ciphertext& mul2(PubPara pp, PubKey epk, Ciphertext ct1, Ciphertext ct2) {  //printf(\"in mul\
\");  DCiphertext dct = CTLinearization2(pp,ct1,ct2);  Ciphertext mct = SwitchKey(pp,epk,dct);  return mct; }
```

_Appendix A.3.