在Python中实现盗窃术(设置攻击)

在Python中实现盗窃术(设置攻击),python,cryptography,public-key-encryption,diffie-hellman,Python,Cryptography,Public Key Encryption,Diffie Hellman,我的任务是重现下面的情节: 它来自(第137-145页) 在中,作者描述了一种称为针对Diffie-Hellman密钥交换的窃贼攻击。特别是,他们编写了以下算法: 现在,作者认为“也许我们可以实现诚实的DHKE和恶意的DHKE,然后比较两种算法的运行时间”。然后,创建了上面的绘图。为此,他们说 “我们已经在ANSI C中实现了Diffie-Hellman协议的污染版本和未污染版本,并使用GNU C v 2.7编译器与RSAREF 2.0库相链接。所有测试都是在Linux系统上运行的,使用的计

我的任务是重现下面的情节:

它来自(第137-145页)

在中,作者描述了一种称为针对Diffie-Hellman密钥交换的窃贼攻击。特别是,他们编写了以下算法:

现在,作者认为“也许我们可以实现诚实的DHKE和恶意的DHKE,然后比较两种算法的运行时间”。然后,创建了上面的绘图。为此,他们说

“我们已经在ANSI C中实现了Diffie-Hellman协议的污染版本和未污染版本,并使用GNU C v 2.7编译器与RSAREF 2.0库相链接。所有测试都是在Linux系统上运行的,使用的计算机带有奔腾II处理器(350 MHz)和64 Mb内存。单个协议的计算时间以10-2秒为单位。”

我想做同样的事情,即实施善恶DH并比较运行时间。这是我产生的代码:

import timeit #used to measure the running time of functions
import matplotlib.pyplot as plt #plot the results
import random
import numpy as np

import pyDH #library for Diffie-Hellman key exchange

X= pyDH.DiffieHellman() #Eve's private key
Y= X.gen_public_key() #Eve's public key

#The three integers a,b,W embedded by Eve
W=3
a=2
b=2

#Honest DH
def public_key():
    d1 = pyDH.DiffieHellman()
    return d1.gen_public_key()

#Malicoius Diffie_Hellman (SETUP)  #line 1-7 in the algorithm
def mal_public_key():        
    d1 = pyDH.DiffieHellman().get_private_key()
    t=random.choice([0,1])
    z1=pow(pyDH.DiffieHellman().g,d1-W*t,pyDH.DiffieHellman().p)
    z2=pow(Y,-a*d1-b,pyDH.DiffieHellman().p)
    z= z1*z2 % pyDH.DiffieHellman().p
    d2=hash(z)
    return pow(pyDH.DiffieHellman().g,d2,pyDH.DiffieHellman().p)



#function that plot the results 
def plot(ntest=100000):
    times = []
    times2=[]

    for i in range(ntest):

        #Running time HONEST Diffie-Hellman (worked two times = two key generations)
        elapse_time = timeit.timeit(public_key, number=2)
        #here I collect the times
        times += [int(round(elapse_time* pow(10, 2) ) )]


        # Running time MALICOIUS Diffie-Hellman
        elapse_time2 = timeit.timeit(mal_public_key, number= 1)
        times2 += [int(round(elapse_time2* pow(10, 2)) )]
    x_axis=[i for i in range(0,20)]

    #collect how many tests last i seconds
    y_axis = [times.count(i) for i in x_axis]
    y_axis2 = [times2.count(i) for i in x_axis]

    plt.plot(x_axis, y_axis, x_axis, y_axis2)
    plt.show()

plot()
我曾经在那里做过诚实的迪菲·赫尔曼。这个代码给了我这个数字:

我认为蓝线(诚实DH)是可以的,但我对橙色线(设置DH)有点怀疑,橙色线与此功能相关:

def mal_public_key():     #line 1-7 in the algorithm
    d1 = pyDH.DiffieHellman().get_private_key() 
    t=random.choice([0,1])
    z1=pow(pyDH.DiffieHellman().g,d1-W*t,pyDH.DiffieHellman().p)
    z2=pow(Y,-a*d1-b,pyDH.DiffieHellman().p)
    z= z1*z2 % pyDH.DiffieHellman().p
    d2 = hash(z)
    return pow(pyDH.DiffieHellman().g,d2,pyDH.DiffieHellman().p)

  • 上述功能是否可以被视为针对DH的设置攻击的“实现”?否则,你会写什么?(对整个代码的任何评论都将不胜感激)
  • 在这篇文章中,你可以读到:
  • “有趣的是,代表受污染实现的曲线 在计算时间的相同值处有一个小峰值 有它唯一的高峰。[…]有两种不同的 每秒调用设备时出现的部件。第一个部件与原始部件相同 […]协议,确切地说,这一部分出现在小峰上 在表示受污染实施的曲线的两个峰值之间 是显而易见的。原因是为了实际使用后的第一部分 协议(即第1-3行)设备不重复第二部分(即第4-7行) 但是很多次。”

    你能给我解释一下这句话吗?特别是,为什么在我的情节中没有小橘子峰?可能是
    mal\u public\u key()
    功能不好

    我正在使用Windows10 64位、8Gb内存、AMD A10-8700P radeon R6、10个计算核心4C+6G 1.80GHz,其中我使用的是Python 3.8。我知道我的电脑应该比作者的好(我想)。也许这会影响结果。然而,在一条椭圆曲线上进行了一个类似的实验,结果与原始曲线很接近(但它是一条椭圆曲线)


    (另一方面,我假设
    a=b=2
    W=3
    ,因为Young和Young没有说明这些整数应该是什么)。

    通过一个具体的例子最容易理解这个问题:Alice有一个为她生成Diffie-Hellman键的设备。在该设备上实现了恶意Diffie-Hellman变体

    恶意DH变体/设置的实现 恶意DH变体的定义如下:,秒。3.1:

    MDH1:对于第一个生成的密钥对,以下内容适用:

    • 私钥c1是小于p-1的随机值。c1储存起来以备日后使用
    • 公钥根据m1=gc1 mod p计算
    • 该设备向Alice提供私钥(c1)和公钥(m1)
    MDH2:对于第二个生成的密钥对,以下内容适用:

    • 随机选择一个t(0或1)
    • z2根据z2=g(c1-Wt)*Y(-ac1-b)mod p计算
    • 私钥c2根据H(z2)计算。这里H是一个加密散列函数。c2储存起来供以后使用
    • 公钥根据m2=gc2 mod p计算
    • 该设备为Alice提供私钥(c2)和公钥(m2)
    MDHi:第三个和后续的密钥对会发生什么情况?对于第二个生成的密钥对使用相同的算法,例如,对于第三个密钥交换,现在使用c2代替c1,m2代替m1,或者通常,如果生成第i个密钥对ci,mi:

    • 随机选择一个t(0或1)
    • zi根据zi=g(ci-1-Wt)*Y(-aci-1-b)mod p计算
    • 私钥ci根据H(zi)计算。这里H是(相同的)加密散列函数。ci被存储以供以后使用
    • 公钥根据mi=gci mod p计算
    • 设备为Alice提供私钥(ci)和公钥(mi)
    请注意,有两类密钥交换进程,MDH1和MDHi,它们将在稍后讨论定时行为时发挥重要作用

    对恶意DH变体发布实施的评估:
    设置(具有通用保护的秘密嵌入式活板门)不是通过问题中发布的恶意DH变体实施的。
    安装程序在两个连续生成的密钥对之间建立关系。这使得可以从两个这样的相关公钥导出上一代密钥的私钥,这两个公钥可以在密钥交换过程中被截获。
    但为此,必须在连续的密钥生成之间传递私钥,以便在最后一代密钥中使用它来建立这种关系。这不会发生在实现中,因此无法实现所需的关系。
    从更技术的角度来看,实现失败的主要原因是MDH1和MDHi案例不是单独实现的,而是作为一个关闭的过程一起实现的。关闭,即在连续调用之间不存储私钥,因此无法传递。因此,实现的后续调用将生成彼此之间不具有所需关系的随机密钥对。
    还请注意,从
    import timeit 
    import matplotlib.pyplot as plt 
    import Crypto.Random.random
    import hashlib
    import pyDH 
    
    DH = pyDH.DiffieHellman()
    xBytes = bytes.fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
    X = int.from_bytes(xBytes, 'big')   #Attacker's private key
    Y = pow(DH.g, X, DH.p)              #Attacker's public key
    W = 3
    a = 1
    b = 2
    ...
    privateKey = -1
    def maliciousDH():
        
        global privateKey
        DH = pyDH.DiffieHellman()
        
        if privateKey == -1:
            privateKeyBytes =  Crypto.Random.get_random_bytes(32)
            privateKey = int.from_bytes(privateKeyBytes, 'big')
            publicKey = pow(DH.g, privateKey, DH.p)
            return publicKey
        else:
            t = Crypto.Random.random.choice([0,1])
            z1 = pow(DH.g, privateKey - W*t, DH.p)
            z2 = pow(Y, -a*privateKey - b, DH.p)
            z = z1 * z2 % DH.p
            privateKey = hashVal(z)
            publicKey = pow(DH.g, privateKey, DH.p)
            return publicKey
            
    def hashVal(value):
        valBytes = value.to_bytes((value.bit_length() + 7) // 8, 'big')
        hashBytes = hashlib.sha256(valBytes).digest()
        hashInt = int.from_bytes(hashBytes, 'big')
        return hashInt
        
    
    def maliciousDHRepeated(nRepeats):
        for repeat in range(nRepeats):  
            publicKey = maliciousDH()
            print('Key Exchange: {0}\nPublic Key:  {1}\nPrivate Key: {2}\n'.format(repeat, publicKey, privateKey))
    maliciousDHRepeated(5)     
    
    def determineSecrets():
        
        # Bob's key pair
        DH = pyDH.DiffieHellman()
        privateKeyBob = DH.get_private_key()
        publicKeyBob = DH.gen_public_key() 
        
        #Alice's key pair (from Key Exchange 4)
        privateKeyAlice = 3330795034653139675928270510449092467425071094588264172648356254062467669676
        publicKeyAlice = 2425486506974365273326155229800001628001265676036580545490312140179127686868492011994151785383963618955049941820322807563286674799447812191829716334313989776868220232473407985110168712017130778639844427996734182094558266926956379518534350404029678111523307272488057571760438620025027821267299005190378538083215345831756055838193240337363440449096741629258341463744397835411230218521658062737568519574165810330776930112569624066663275971997360960116063343238010922620695431389619027278076763449139206478745130163740678443228451977971659504896731844067323138748945493668050217811755122279988027033740720863980805941221
        
        #Secrets
        secretBob = pow(publicKeyAlice, privateKeyBob, DH.p)
        secretAlice  = pow(publicKeyBob, privateKeyAlice, DH.p)
        
        print("Bob's secret:    {0}\nAlices's secret: {1}\n".format(secretBob, secretAlice))
        
    determineSecrets()
    
    def stealPrivateKey(currentPublicKey, previousPublicKey):
        r = pow(previousPublicKey, a, DH.p) * pow(DH.g, b, DH.p) % DH.p
        u = previousPublicKey * pow(r, -X, DH.p) % DH.p
        if currentPublicKey == pow(DH.g, hashVal(u), DH.p):
            return hashVal(u)
        v = u * pow(DH.g, -W, DH.p) % DH.p
        if currentPublicKey == pow(DH.g, hashVal(v), DH.p):
            return hashVal(v)
        return -1
    
    previousPublicKey = 10734077925995936749728900841226052313744498030619019606720177499132029904239020745125405126713523340876577377685679745194099270648038862447581601078565944941187694038253454951671644736332158734087472188874069332741118722988900754423479460535064533867667442756344440676583179886192206646721969399316522205542274029421077750159152806910322245234676026617311998560439487358561468993386759527957631649439920242228063598908755800970876077082845023854156477810356816239577567741067576206713910926615601025551542922545468685517450134977861564984442071615928397542549964474043544099258656296307792809119600776707470658907443
    currentPublicKey = 2425486506974365273326155229800001628001265676036580545490312140179127686868492011994151785383963618955049941820322807563286674799447812191829716334313989776868220232473407985110168712017130778639844427996734182094558266926956379518534350404029678111523307272488057571760438620025027821267299005190378538083215345831756055838193240337363440449096741629258341463744397835411230218521658062737568519574165810330776930112569624066663275971997360960116063343238010922620695431389619027278076763449139206478745130163740678443228451977971659504896731844067323138748945493668050217811755122279988027033740720863980805941221
    currentPrivateKey = stealPrivateKey(currentPublicKey, previousPublicKey)
    print(currentPrivateKey)
    
    def standardDH():
        
        DH = pyDH.DiffieHellman()
        privateKeyBytes = Crypto.Random.get_random_bytes(32)
        privateKey = int.from_bytes(privateKeyBytes, 'big')
        publicKey = pow(DH.g, privateKey, DH.p)
        return publicKey
    
    def plot(nTests = 1000, nKeyExPerTest = 10):
        
        global privateKey
        
        timesStandardDH = []
        timesMaliciousDH = []
    
        for test in range(nTests): 
                   
            for keyExPerTest in range(nKeyExPerTest):
                elapseTimeStandardDH = timeit.timeit(standardDH, number = 1)
                timesStandardDH += [int(round(elapseTimeStandardDH * pow(10, 3) ) )]
            privateKey = -1
            for keyExPerTest in range(nKeyExPerTest):
                elapseTimeMaliciousDH = timeit.timeit(maliciousDH, number = 1)
                timesMaliciousDH += [int(round(elapseTimeMaliciousDH * pow(10, 3)) )]
                        
        x_axis=[i for i in range(0, 50)]       
        y_axisStandardDH = [timesStandardDH.count(i) for i in x_axis]
        y_axisMaliciousDH = [timesMaliciousDH.count(i) for i in x_axis]
    
        plt.plot(x_axis, y_axisStandardDH, x_axis, y_axisMaliciousDH)
        plt.show()
    
    plot()