2021SC@SDUSC
通过前面的三篇博客,我们已经对BGV方案有了初步的认知,从这篇博客开始就进入了我们的源码分析模块了,本篇博客重点分析的是bgvrns.cpp的密钥生成模块——KeyGen。
bgvrns.cpp源文件实现了Brakerski-Gentry-Vaikuntanathan
方案的Residue Number System (RNS)
的变体。
KeyGen模块在源文件的开头部分:
template <class Element>
LPKeyPair<Element> LPAlgorithmBGVrns<Element>::KeyGen(CryptoContext<Element> cc,
bool makeSparse) {
LPKeyPair<Element> kp(std::make_shared<LPPublicKeyImpl<Element>>(cc),
std::make_shared<LPPrivateKeyImpl<Element>>(cc));
const auto cryptoParams =
std::static_pointer_cast<LPCryptoParametersBGVrns<Element>>(
cc->GetCryptoParameters());
const shared_ptr<ParmType> elementParams = cryptoParams->GetElementParams();
...
}
KeyGen方法传入两个参数:CryptoContext<Element> cc, bool makeSparse。返回一个LPKeyPair<>泛型对象,从下面一行得知,该对象是由一组公钥与私钥。
根据palisade_manual.pdf中Scheme章的内容,我们可以得知,cryptoParams保存着BGV方案的特定的配置参数,原文如下:
In order to use a particular Scheme, its configuration parameters must be specified. The particular configuration parameters for each scheme are stored in a CryptoParameters class (the full class name is LPCryptoParameters) that is particular for that scheme. The classes for CryptoParameters for each scheme are unique, but they all share several characteristics:
cryptoParamsy由LPCryptoParametersBGVrns生成,我们可以从bgvrns.h中看到这个类的定义:
/** * @brief Crypto parameters class for RLWE-based schemes. * * @tparam Element a ring element. */ template <class Element> class LPCryptoParametersBGVrns : public LPCryptoParametersRLWE<Element> { using IntType = typename Element::Integer; using ParmType = typename Element::Params; using DggType = typename Element::DggType; using DugType = typename Element::DugType; using TugType = typename Element::TugType; public: /** * Default Constructor. */ LPCryptoParametersBGVrns() : LPCryptoParametersRLWE<Element>(), m_ksTechnique(BV), m_msMethod(MANUAL), m_numPartQ(0), m_numPerPartQ(0) {} /** * Copy constructor. * * @param rhs - source */ LPCryptoParametersBGVrns(const LPCryptoParametersBGVrns& rhs) : LPCryptoParametersRLWE<Element>(rhs), m_ksTechnique(BV), m_msMethod(MANUAL), m_numPartQ(0), m_numPerPartQ(0) {} LPCryptoParametersBGVrns(shared_ptr<ParmType> params, const PlaintextModulus& plaintextModulus, float distributionParameter, float assuranceMeasure, float securityLevel, usint relinWindow, MODE mode, int depth = 1, int maxDepth = 2, KeySwitchTechnique ksTech = BV, ModSwitchMethod msMethod = MANUAL) : LPCryptoParametersRLWE<Element>( params, EncodingParams( std::make_shared<EncodingParamsImpl>(plaintextModulus)), distributionParameter, assuranceMeasure, securityLevel, relinWindow, depth, maxDepth, mode) { m_ksTechnique = ksTech; m_msMethod = msMethod; m_numPartQ = 0; m_numPerPartQ = 0; } LPCryptoParametersBGVrns(shared_ptr<ParmType> params, EncodingParams encodingParams, float distributionParameter, float assuranceMeasure, float securityLevel, usint relinWindow, MODE mode, int depth = 1, int maxDepth = 2, KeySwitchTechnique ksTech = BV, ModSwitchMethod msMethod = MANUAL) : LPCryptoParametersRLWE<Element>( params, encodingParams, distributionParameter, assuranceMeasure, securityLevel, relinWindow, depth, maxDepth, mode) { m_ksTechnique = ksTech; m_msMethod = msMethod; m_numPartQ = 0; m_numPerPartQ = 0; } /** * Destructor. */ virtual ~LPCryptoParametersBGVrns() {} //该类的具体的方法 ... }
该类有一个无参数的构造函数,一个赋值函数,两个有参数的构造函数与一个析构函数,以及许多类方法组成。
继续分析bgvrns.cpp中的KeyGen函数,接着KeyGen方法初始化三个生成器用于后续采样。
const DggType &dgg = cryptoParams->GetDiscreteGaussianGenerator();
DugType dug;
TugType tug;
- DGG:离散高斯分布生成器
- Dug:离散均匀分布生成器 (discrete uniform generator)
- Tug:三元均匀分布生成器
由系列文章(三)BGV原理分析中,我们知道public Key的生成依赖于一个公式:
public key由两部分组成,代码紧接着就开始构造pk:
// Generate the element "a" of the public key
//——构造a,通过离散均匀分布器采样得到
Element a(dug, elementParams, Format::EVALUATION);
// Generate the secret key
//——构造密钥
Element s;
// Get the plaintext modulus
//——获取明文模块
const auto t = cryptoParams->GetPlaintextModulus();
// public key is generated and set
// privateKey->MakePublicKey(a, publicKey);
//——利用离散高斯分布器生成噪声e
Element e(dgg, elementParams, Format::COEFFICIENT);
e.SetFormat(Format::EVALUATION);
Element b = t * e - a * s;//公钥第一部分
然后将获得的密钥赋给KeyPair(secretKey,publicKey),返回KeyPair对象。
kp.secretKey->SetPrivateElement(std::move(s));
kp.publicKey->SetPublicElementAtIndex(0, std::move(b));
kp.publicKey->SetPublicElementAtIndex(1, std::move(a));
return kp;
到这里KeyGen()函数就执行完成了,主要就是生成的公钥与密钥,并且返回了它们。