BCP加密算法改進方案(DT-PKC)復(fù)現(xiàn)記錄

1.簡介

  • 相關(guān)論文:An efficient privacy-preserving outsourced calculation toolkit with multiple keys政勃。這篇論文由Ximeng LIU,RobertH.DENG,Kim-Kwang Raymond CHOO,Jian WENG發(fā)表于TIFS(IEEE Transactions on Information Forensics and Security)渠概。該論文針對BCP算法構(gòu)建的多密鑰下同態(tài)運算的方案提出一些改進(改進后的方案稱為:DT-PKC)赐稽,將可以解密的系統(tǒng)主密鑰(MK),拆分為兩個部分,任何一個部分都不能單獨解密。這樣可以解決中心節(jié)點擁有主密鑰所產(chǎn)生的安全性問題。
  • 本文主要介紹其對BCP算法的改進部分,即如何拆分主密鑰及拆分主密鑰后的解密運算教翩。
  • 關(guān)于BCP加密算法的簡介:參考文章BCP加密算法復(fù)現(xiàn)記錄

2.DT-PKC復(fù)現(xiàn)記錄

2.1 環(huán)境配置

2.2 重要步驟說明

  • 導(dǎo)入依賴的庫及函數(shù)
from charm.toolbox.integergroup import IntegerGroup
from charm.schemes.pkenc.pkenc_rsa import RSA_Enc, RSA_Sig
from charm.core.math.integer import integer,randomBits,random,randomPrime,isPrime,encode,decode,hashInt,bitsize,legendre,gcd,lcm,serialize,deserialize,int2Bytes,toInt
  • 第一步:初始化饱亿,生成公共參數(shù)及系統(tǒng)主密鑰。
    首先選取一個安全參數(shù)secparam闰靴,之后選取兩個安全素數(shù)(safe prime)p,q彪笼,使其位長度(bit length)為secparam,根據(jù)安全素數(shù)的定義蚂且,p^{'} = (p-1)/2q^{'}=(q-1)/2也是素數(shù)配猫。之后計算N = pq\lambda = lcm(p-1,q-1)/2lcm:最小公倍數(shù))。定義一個函數(shù):L(x) = (x-1)/N杏死。選取一個(p-1)(q-1)/2階元g泵肄,g可以通過隨機選取a\in Z^{*}_{N^2},計算g = -a^{2N}獲得捆交,相關(guān)論文:Universal Hash Proofs and a Paradigm for Adaptive Chosen Ciphertext Secure Public-Key Encryption。這樣,系統(tǒng)的主密鑰MK = \lambda腐巢。
    相關(guān)代碼:
def __init__(self,secparam = 128):
        self.p,self.q = randomPrime(secparam,True),randomPrime(secparam,True)
        self.pp = (self.p - 1)/2
        self.qq = (self.q - 1)/2
        self.N = self.p * self.q
        self.N2 = self.N**2
        self.lamda = lcm(self.p-1,self.q-1)/2
        
        # 一下為選取一個(p-1)(q-1)/2階元
        # 先隨機選取a
        self.a = random(self.N2)
        # 計算a^2N
        tmp = self.a**(2*self.N)
        # 計算-a^2N
        self.g = (int(self.N2)-int(tmp))%self.N2
        self.mk = self.lamda
  • 第二步:密鑰生成品追。
    隨機選取\theta \in [1,N/4],計算h = g^{\theta} mod N^2冯丙。公鑰pk = (N,g,h)肉瓦,私鑰sk = \theta
    相關(guān)代碼:
    def KeyGen(self):
        theta = random(self.N/4)
        h = self.g**(theta)%self.N2
        pk = {"N":self.N,"g":self.g,"h":h}
        sk = theta
        return pk,sk
  • 第三步:加密胃惜。
    明文空間:m\in Z_N泞莉,選取隨機數(shù)r \in [1,N/4]。這樣使用公鑰pk加密m得到密文可以表示為[m]_{pk} = \{ T_1,T_2 \}蛹疯,T_1 = h^r(1+mN)modN^2T_2 = g^r mod N^2热监。
    相關(guān)代碼:
    def Encrypt(self,pk,plaintext):
        r = random(self.N/4)
        T1 = int(pk["h"]**(r))*int(1+plaintext*self.N) % self.N2
        T2 = pk["g"]**(r) % self.N2
        ciphertext = {"T1":T1,"T2":T2}
        return ciphertext
  • 第四步:使用私鑰解密捺弦。
    密文[m]_{pk} = \{ T_1,T_2 \}可以由私鑰sk = \theta解密,解密公式:m = L({T_1 \over T_2^\theta} mod N^2)孝扛。
    相關(guān)代碼:
    def Decrypt(self,ciphertext,sk):
        T1 = ciphertext["T1"]
        T2 = ciphertext["T2"]
        tmp = (T1 / (T2**sk)) % self.N2
        m = (int(tmp)-1)/self.N
        return m
  • 第五步:使用主密鑰解密列吼。
    密文[m]_{pk} = \{ T_1,T_2 \}還可以由主密鑰MK = \lambda解密。首先計算T_1^\lambda mod N^2 = h^{\lambda r}(1+mN\lambda) mod N^2=g^{\lambda \theta r}(1+mN\lambda)mod N^2 = (1+mN\lambda)苦始,由于gcd(\lambda,N) = 1寞钥,m = L(T_1^\lambda mod N^2)\lambda^{-1}mod N
    相關(guān)代碼:
    def DecryptMK(self,ciphertext,mk):
        tmp = ciphertext["T1"]**(mk) % self.N2
        mk = mk % self.N
        mk_1 = mk**(-1)
        
        m = ((int(tmp)-1)/self.N)*int(mk_1)%self.N
        return integer(m)
  • 第六步:主密鑰切分陌选。
    主密鑰MK = \lambda可以被隨機切分為兩個部分\lambda_1,\lambda_2理郑,需要滿足\lambda_1+\lambda_2\equiv0 mod \lambda并且\lambda_1+\lambda_2\equiv1 mod N^2。下面分析可以這樣切分的原因:
    根據(jù)中國剩余定理咨油,由于gcd(\lambda,N^2)=1您炉,因此存在s,使得s\equiv0mod \lambda并且s \equiv 1modN^2役电,且s = \lambda \cdot(\lambda^{-1}mod N^{2})mod \lambda N^{2}赚爵,參考:C. Ding, Chinese Remainder Theorem. Singapore: World Scientific,1996.
    這樣,只需隨機選取\lambda_1,\lambda_2法瑟,使得\lambda_1+\lambda_2=s即可冀膝,相關(guān)代碼:
    def SplitMK(self,mk):
        mk = mk % self.N
        mk_1 = mk**(-1)
        tmp = int(mk)*int(int(mk_1)%self.N2)
        modulus = int(mk)*int(self.N2)
        s = tmp % modulus
        lamda1 = random(s)
        lamda2 = s - int(lamda1)
        return integer(lamda1),integer(lamda2)
  • 第七步:利用切分后的主密鑰進行解密。

這一步又可以分為兩小步:

1)利用部分主密鑰\lambda_1得到中間結(jié)果CT_1CT_1 = {(T_1)}^{\lambda_1}=g^{\lambda_1 r \theta }(1+mN\lambda_1)mod N^2霎挟。相關(guān)代碼:

    def PSDec1(self,ciphertext,lamda1):
        ct1 = ciphertext["T1"]**(lamda1)
        return ct1

2)利用部分主密鑰\lambda_2與中間結(jié)果CT_1計算首先得到CT_2窝剖,之后利用CT_1,CT_2計算得到結(jié)果:CT_2={(T_1)}^{\lambda_2}={(T_1)}^{\lambda_2}=g^{\lambda_2 r \theta }(1+mN\lambda_2)mod N^2,T^{"}=CT_1 \cdot CT_2m = L(T^{"})酥夭。相關(guān)代碼:

    def PSDec2(self,ciphertext,lamda2,ct1):
        ct2 = ciphertext["T1"]**(lamda2)
        T = ct1*ct2
        m = (int(T)-1)/int(self.N)
        return integer(int(m))
  • 完整代碼:
from charm.toolbox.integergroup import IntegerGroup
from charm.schemes.pkenc.pkenc_rsa import RSA_Enc, RSA_Sig
from charm.core.math.integer import integer,randomBits,random,randomPrime,isPrime,encode,decode,hashInt,bitsize,legendre,gcd,lcm,serialize,deserialize,int2Bytes,toInt

class DTPKC():
    def __init__(self,secparam = 128):
        self.p,self.q = randomPrime(secparam,True),randomPrime(secparam,True)
        self.pp = (self.p - 1)/2
        self.qq = (self.q - 1)/2
        self.N = self.p * self.q
        self.N2 = self.N**2
        self.lamda = lcm(self.p-1,self.q-1)/2
        
        self.a = random(self.N2)
        tmp = self.a**(2*self.N)
        self.g = (int(self.N2)-int(tmp))%self.N2
        self.mk = self.lamda

    def GetMK(self):
        return self.mk
    
    def KeyGen(self):
        theta = random(self.N/4)
        h = self.g**(theta)%self.N2
        pk = {"N":self.N,"g":self.g,"h":h}
        sk = theta
        return pk,sk

    def Encrypt(self,pk,plaintext):
        r = random(self.N/4)
        T1 = int(pk["h"]**(r))*int(1+plaintext*self.N) % self.N2
        T2 = pk["g"]**(r) % self.N2
        ciphertext = {"T1":T1,"T2":T2}
        return ciphertext

    def Decrypt(self,ciphertext,sk):
        T1 = ciphertext["T1"]
        T2 = ciphertext["T2"]
        tmp = (T1 / (T2**sk)) % self.N2
        m = (int(tmp)-1)/self.N
        return m

    def DecryptMK(self,ciphertext,mk):
        tmp = ciphertext["T1"]**(mk) % self.N2
        mk = mk % self.N
        mk_1 = mk**(-1)
        
        m = ((int(tmp)-1)/self.N)*int(mk_1)%self.N
        return integer(m)

    def SplitMK(self,mk):
        mk = mk % self.N
        mk_1 = mk**(-1)
        tmp = int(mk)*int(int(mk_1)%self.N2)
        modulus = int(mk)*int(self.N2)
        s = tmp % modulus
        lamda1 = random(s)
        lamda2 = s - int(lamda1)
        return integer(lamda1),integer(lamda2)

    def PSDec1(self,ciphertext,lamda1):
        ct1 = ciphertext["T1"]**(lamda1)
        return ct1

    def PSDec2(self,ciphertext,lamda2,ct1):
        ct2 = ciphertext["T1"]**(lamda2)
        T = ct1*ct2
        m = (int(T)-1)/int(self.N)
        return integer(int(m))

3.測試

  • 測試代碼:
if __name__ == "__main__":
    
    dt_pkc = DTPKC()
    mk = dt_pkc.GetMK()
    print("mk is:",mk)
    pk,sk = dt_pkc.KeyGen()
    print("------------------------------")
    print("pk is:",pk,"sk is:",sk)
    plaintext = 1024
    print("------------------------")
    print("plaintext is:",plaintext)
    ciphertext = dt_pkc.Encrypt(pk,1024)
    print("------------------------")
    print("ciphertext is:",ciphertext)
    m1 = dt_pkc.Decrypt(ciphertext,sk)
    print("-------------------------")
    print("Using sk to decrypt ciphertext,result is:",m1)
    m2 = dt_pkc.DecryptMK(ciphertext,mk)
    print("-------------------------")
    print("Using mk to decrypt ciphertext,result is:",m2)

    lamda1,lamda2 = dt_pkc.SplitMK(mk)
    print("-------------------------")
    print("lamda1 is:",lamda1)
    print("lamda2 is:",lamda2)
    print("now we use lamda1 and lamda2 to decrypt:")
    ct1 = dt_pkc.PSDec1(ciphertext,lamda1)
    print("-------------------------")
    print("The middle result is:",ct1)
    print("-------------------------")
    m3 = dt_pkc.PSDec2(ciphertext,lamda2,ct1)
    print("Using lamda1 and lamda2 to decrypt ciphertext,result is:",m3)
  • 測試結(jié)果:加解密運算正確
mk is: 22338062150910213287096358186084458203294109371215927224896109781996280749289
------------------------------
pk is: {'N': 89352248603640853148385432744337832813774312926927445628961672829724410984689, 'g': 5796069204765623542573279877045795421667308892848339471072299243822410092499008991382506301127284670227987017148628307351991077555531163469032056732101199 mod 7983824330526838791274511562029416677868477739833493115159981949744753275885355914958363600037866383924640499394589563036708131942917863905100086592426721, 'h': 7935721887038910245545505888433794372349511663547277093912096084521177913556538675688906850177251874779422538574782147394495941080326621060611267735334082 mod 7983824330526838791274511562029416677868477739833493115159981949744753275885355914958363600037866383924640499394589563036708131942917863905100086592426721} sk is: 76204058112965194407732331957567427660809926855819726246456305039472675957297 mod 89352248603640853148385432744337832813774312926927445628961672829724410984689
------------------------
plaintext is: 1024
------------------------
ciphertext is: {'T1': 1189202078396194739872313433810947540535206630405742685355335605588797450138354847755661690141041049479509074532983600670745074186493313833872690728336707 mod 7983824330526838791274511562029416677868477739833493115159981949744753275885355914958363600037866383924640499394589563036708131942917863905100086592426721, 'T2': 2031968094987867056707267176620567341361755305640188891998505629184921793767586718829208072634700218440322730486634379570080555010326243084347844702963534 mod 7983824330526838791274511562029416677868477739833493115159981949744753275885355914958363600037866383924640499394589563036708131942917863905100086592426721}
-------------------------
Using sk to decrypt ciphertext,result is: 1024
-------------------------
Using mk to decrypt ciphertext,result is: 1024
-------------------------
lamda1 is: 1505802704812095957081963280847475955421013132898588206367067311511714138058340080719320579687618270014411099365999155016669463468104328753042522940931295
lamda2 is: 260804022002047759634149184903924934389916372259491181826426268699503308739361628589967413175895360769713621921485147556575752847045942699929051799977835
now we use lamda1 and lamda2 to decrypt:
-------------------------
The middle result is: 3433002371868990949360033462226377385418613313243722104147586473147340479553469853206909391421965360453688842498974729295524950767714321345265678668705251 mod 7983824330526838791274511562029416677868477739833493115159981949744753275885355914958363600037866383924640499394589563036708131942917863905100086592426721
-------------------------
Using lamda1 and lamda2 to decrypt ciphertext,result is: 1024
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枯芬,一起剝皮案震驚了整個濱河市论笔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌千所,老刑警劉巖狂魔,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異淫痰,居然都是意外死亡最楷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門待错,熙熙樓的掌柜王于貴愁眉苦臉地迎上來籽孙,“玉大人,你說我怎么就攤上這事火俄》附ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵瓜客,是天一觀的道長适瓦。 經(jīng)常有香客問我,道長谱仪,這世上最難降的妖魔是什么玻熙? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮疯攒,結(jié)果婚禮上嗦随,老公的妹妹穿的比我還像新娘。我一直安慰自己敬尺,他們只是感情好枚尼,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著砂吞,像睡著了一般姑原。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呜舒,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天锭汛,我揣著相機與錄音,去河邊找鬼袭蝗。 笑死唤殴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的到腥。 我是一名探鬼主播朵逝,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼乡范!你這毒婦竟也來了配名?” 一聲冷哼從身側(cè)響起啤咽,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎渠脉,沒想到半個月后宇整,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡芋膘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年鳞青,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片为朋。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡臂拓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出习寸,到底是詐尸還是另有隱情胶惰,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布霞溪,位于F島的核電站孵滞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏威鹿。R本人自食惡果不足惜剃斧,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一轨香、第九天 我趴在偏房一處隱蔽的房頂上張望忽你。 院中可真熱鬧,春花似錦臂容、人聲如沸科雳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糟秘。三九已至,卻和暖如春球散,著一層夾襖步出監(jiān)牢的瞬間尿赚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工蕉堰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凌净,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓屋讶,卻偏偏與公主長得像冰寻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子皿渗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容