所谓的加密,其实是明文空间到密文空间的映射关系。明文空间里面的元素,叫做明文,是我们想要保护的信息,通常会含有一些特殊的信息。常见的明文有图像,视频、个人资料等等。明文空间里面的元素,我们通常叫做密文,是用来保护明文的。对于一个安全的加密来说,如果不知道解密密钥,密文应该是十分接近随机数,其分布在密文空间应该是均匀随机的。密文本身不应该含有明文的任何信息,也就是语义安全性。
同态加密是一种特殊的加密方法。他可以允许我们直接对密文进行运算,其解密后的结果就是对应明文运算后的结果。这对于隐私计算是一个非常好用的工具,使得很多隐私计算协议变得简单直接。
假设加密函数为 c = E n ( m , P k ) c=\mathtt{En}(m,P_k) c=En(m,Pk),输入为明文 m m m和加密密钥(通常是公钥) P k P_k Pk.输出一个密文 c c c.
解密函数为 m = D e ( c , S k ) m=\mathtt{De}(c,S_k) m=De(c,Sk),输入为密文 c c c和解密密钥 S k S_k Sk.
加法同态是说 m 1 + m 2 = D e ( E n ( m 1 , P k ) ⨁ E n ( m 2 , P k ) , S k ) m_1+m_2=\mathtt{De}(\mathtt{En}(m_1,P_k)\bigoplus \mathtt{En}(m_2,P_k),S_k) m1+m2=De(En(m1,Pk)⨁En(m2,Pk),Sk). 其中 ⨁ \bigoplus ⨁是定义的两个密文的加法。
乘法同态是说 m 1 × m 2 = D e ( E n ( m 1 , P k ) ⨂ E n ( m 2 , P k ) , S k ) m_1\times m_2=\mathtt{De}(\mathtt{En}(m_1,P_k)\bigotimes \mathtt{En}(m_2,P_k),S_k) m1×m2=De(En(m1,Pk)⨂En(m2,Pk),Sk).其中 ⨂ \bigotimes ⨂是定义的两个密文的乘法。
OpenFHE是一个比较成熟的使用C++写的同态加密库[1],实现了基于RLWE的常见的同态加密方案,包括BGV [2],BFV [3],CKKS [4],FHEW/TFHE [5]. 具体实现的版本是剩余整数系统(RNS)变体,也就是使用64位的整数去表示大整数。
支持的运算有公钥加密,私钥加密,同态加法,层级同态乘法,自举(bootstrapping),密钥交换,最新的进展可以查阅他们的github网站OpenFHE github。
OpenFHE 使用的是 Cmake 来组织编译,所以,在编译之前,首先需要确保你已经配置好了 Cmake 的环境。下面主要介绍在 linux 上安装的方法。
如果你的网络没有问题,那么安装是一件比较简单愉快的事情。
第一步要做的事情就是从 github 上下载源代码:
git clone https://github.com/openfheorg/openfhe-development.git
那么遇到没办法直接用命令下载怎么办呢?可能服务器暂时不支持访问 github 网站。这时候,你可以直接去OpenFHE github下载 ZIP 的压缩包。然后把压缩包上传到你的 linux 机器上。但是你会发现,下载压缩包的方法并不是很愉快的,如果编译的时候你的网络还是不能访问 github 的话,会出错。因为直接下载的 ZIP 里面的第三方依赖库没有自动下载。你会发现在目录 \openfhe-development-main\third-party\ 下的几个文件夹是空的。
下载 ZIP 压缩包 openfhe-development-main.zip 并上传到服务器。使用下面命令解压:
unzip openfhe-development-main.zip
然后进入下列路径:
cd openfhe-development-main/third-party
使用 ls 命令查看,里面有四个目录 cereal google-benchmark google-test gperftools, 这时候,如果这四个目录是空的,那么需要到 github 上下载。在OpenFHE github里面,找到 third-party目录,然后点进去,里面是4个链接。分别点进去下载 ZIP 压缩包,然后解压到对应的目录。
下面演示 cereal 的解压。首先将下载的 cerea-***.zip文件解压到对应目录
unzip -o cereal-your number.zip -d openfhe-development-main/third-party
然后进入 openfhe-development-main/third-party 目录,将解压后的文件改名为 cereal,(你应该先删除原来的 cereal 目录)
其他三个类似。
当源文件下载完成后,剩下的就比较简单了。
首先进入 OpenFHE 的源文件目录,然后使用 mkdir build 建立一个新的名叫 build 的文件夹,进入 build 文件夹.
cmake ../
生成编译的make文件。可以在 cmake 的时候指定最后安装的目录
cmake ../ -DCMAKE_INSTALL_PREFIX=/my_path
然后你会看到输出里面有这句话:
***** INSTALL IS AT /my_path; to change, run cmake with -DCMAKE_INSTALL_PREFIX=/your/path
然后在命令行继续输入
make
这个命令会执行编译,将源文件编译为可执行文件和库。可以使用" -j"选项使用多线程编译,如" make -j4 ".
编译完成后,就可以将 OpenFHE 安装到常用路径了。
make install
如果你安装到默认路径 \usr\lcoal 那么你可能需要使用 sudo 命令才能安装 “sudo make install”.
下面给出一个简单的测试源代码 test.cpp:
/*
test.cpp OpenFHE test code by zyf.
*/
#include
#include"openfhe.h"
//The functions or classes of OpenFHE are in the namespace lbcrypto
using namespace lbcrypto;
using namespace std;
int main(){
// set the parameters of bgv
CCParams<CryptoContextBGVRNS> parameters;
parameters.SetMultiplicativeDepth(0);
parameters.SetPlaintextModulus(536903681);
parameters.SetSecurityLevel(HEStd_128_classic);
CryptoContext<DCRTPoly> cryptoContext = GenCryptoContext(parameters);
cryptoContext->Enable(PKE);
cryptoContext->Enable(KEYSWITCH);
cryptoContext->Enable(LEVELEDSHE);
KeyPair<DCRTPoly> keyPair;
keyPair = cryptoContext->KeyGen();
vector<int64_t> v1 = {-1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
cout<<"The original data is ";
for(size_t i=0;i<v1.size();i++){
cout<<v1[i]<<" ";
}
cout<<endl;
Plaintext p1;
p1=cryptoContext->MakePackedPlaintext(v1);
Ciphertext<DCRTPoly> c1 = cryptoContext->Encrypt(keyPair.publicKey, p1);
Plaintext p2;
cryptoContext->Decrypt(keyPair.secretKey,c1,&p2);
cout<<p2<<endl;
}
在test.cpp同一个目录添加 CMakeLists.txt 文件:
cmake_minimum_required (VERSION 3.5.1)
project(demo CXX)
set(CMAKE_CXX_STANDARD 17)
option( BUILD_STATIC "Set to ON to include static versions of the library" OFF)
find_package(OpenFHE)
set( CMAKE_CXX_FLAGS ${OpenFHE_CXX_FLAGS} )
include_directories( ${OPENMP_INCLUDES} )
include_directories( ${OpenFHE_INCLUDE} )
include_directories( ${OpenFHE_INCLUDE}/third-party/include )
include_directories( ${OpenFHE_INCLUDE}/core )
include_directories( ${OpenFHE_INCLUDE}/pke )
### add directories for other OpenFHE modules as needed for your project
link_directories( ${OpenFHE_LIBDIR} )
link_directories( ${OPENMP_LIBRARIES} )
if(BUILD_STATIC)
set( CMAKE_EXE_LINKER_FLAGS "${OpenFHE_EXE_LINKER_FLAGS} -static")
link_libraries( ${OpenFHE_STATIC_LIBRARIES} )
else()
set( CMAKE_EXE_LINKER_FLAGS ${OpenFHE_EXE_LINKER_FLAGS} )
link_libraries( ${OpenFHE_SHARED_LIBRARIES} )
endif()
add_executable(test test.cpp )
然后使用
cmake ./
make
就可以生成可执行文件 test 了。如果不能找到 OpenFHE库,可以尝试手动设置,将安装的路径添加到搜索路径中,如在 find_package 命令之前使用 include_directories(your path)将你的安装路径添加进去。
[1] Al Badawi, Ahmad, et al. “Openfhe: Open-source fully homomorphic encryption library.” Proceedings of the 10th Workshop on Encrypted Computing & Applied Homomorphic Cryptography. 2022.
[2] Brakerski, Zvika, Craig Gentry, and Vinod Vaikuntanathan. “(Leveled) fully homomorphic encryption without bootstrapping.” ACM Transactions on Computation Theory (TOCT) 6.3 (2014): 1-36.
[3] Fan, Junfeng, and Frederik Vercauteren. “Somewhat practical fully homomorphic encryption.” Cryptology ePrint Archive (2012).
[4] Cheon, Jung Hee, et al. “Homomorphic encryption for arithmetic of approximate numbers.” Advances in Cryptology–ASIACRYPT 2017: 23rd International Conference on the Theory and Applications of Cryptology and Information Security, Hong Kong, China, December 3-7, 2017, Proceedings, Part I 23. Springer International Publishing, 2017.
[5] Ducas, Léo, and Daniele Micciancio. “FHEW: bootstrapping homomorphic encryption in less than a second.” Annual international conference on the theory and applications of cryptographic techniques. Berlin, Heidelberg: Springer Berlin Heidelberg, 2015.