在 python 中实现 Diffie-Hellman。共享密钥未匹配

Implementing Diffie-Hellman in python. Shared secret keys aren't getting matched

提问人:knk 提问时间:11/17/2023 最后编辑:knk 更新时间:11/17/2023 访问量:37

问:

希望一切都好。我正在尝试在 Python 中实现Diffie_Hellman。我读到,为了更好的安全性,建议将 Prime p 长度应至少为 2048 位,并且 G 应生成大小至少为 2^128 的子组。我编写了用于管理此问题的代码,但遗憾的是,我获得的共享密钥对于发送方和接收方来说都不匹配。

代码如下:

import random
import secrets
from sympy import isprime

def get_large_prime(bit_length):
    while True:
        prime_candidate = random.getrandbits(bit_length)
        # Ensure the number has the correct bit length and is odd
        prime_candidate |= (1 << bit_length - 1) | 1
        if isprime(prime_candidate):
            return prime_candidate

def find_generator(p):
    """Find a generator for the multiplicative group modulo p."""
    # Candidates for g that often generate large subgroups
    candidate_values = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]

    for g_candidate in candidate_values:
        if pow(g_candidate, (p-1)//2, p) != 1 and pow(g_candidate, (p-1)//3, p) != 1:
            return g_candidate

    # If none of the candidates work, use a generic search
    g = 2
    subgroup_size = 1
    while subgroup_size < 2**128:
        g += 1
        subgroup_size = pow(g, (p-1)//2, p)
    return g

def generate_private_key():
    """Generate a private key."""
    return secrets.randbelow(2**128 - 1) + 2  # Use secrets module for more secure random number generation

def calculate_public_key(generator, private_key, prime):
    """Calculate the public key."""
    return pow(generator, private_key, prime)

def calculate_shared_secret(public_key, private_key, prime):
    """Calculate the shared secret key."""
    return pow(public_key, private_key, prime)

if __name__ == '__main__':
    bit_length = 2048

    # Generate a large prime number and a generator for the sender
    sender_prime = get_large_prime(bit_length)
    sender_generator = find_generator(sender_prime)
    sender_private_key = generate_private_key()
    sender_public_key = calculate_public_key(sender_generator, sender_private_key, sender_prime)

    # Generate a large prime number and a generator for the receiver
    receiver_prime = get_large_prime(bit_length)
    receiver_generator = find_generator(receiver_prime)
    receiver_private_key = generate_private_key()
    receiver_public_key = calculate_public_key(receiver_generator, receiver_private_key, receiver_prime)

    # Exchange public keys
    sender_shared_secret = calculate_shared_secret(receiver_public_key, sender_private_key, sender_prime)
    receiver_shared_secret = calculate_shared_secret(sender_public_key, receiver_private_key, receiver_prime)

    print(f"Sender's {bit_length}-bit prime is:\n{sender_prime}")
    print(f"Sender's generator for the group is:\n{sender_generator}")
    print(f"Sender's private key is:\n{sender_private_key}")
    print(f"Sender's public key is:\n{sender_public_key}")
    print(f"Sender's shared secret key is:\n{sender_shared_secret}\n")

    print(f"Receiver's {bit_length}-bit prime is:\n{receiver_prime}")
    print(f"Receiver's generator for the group is:\n{receiver_generator}")
    print(f"Receiver's private key is:\n{receiver_private_key}")
    print(f"Receiver's public key is:\n{receiver_public_key}")
    print(f"Receiver's shared secret key is:\n{receiver_shared_secret}")

这是我得到的输出:

Sender's 2048-bit prime is:
32221686490172290560951951774790258460511868236561699121155218960182686672268366824979336043526909174261098452725855386505897506209694348499911039436641080845094359385613013005904354882991155555969461828748177396576617140218457422066028808302301029566190549321140606549375380639043920388602437077015364721949831852984663199820354046717364480597620765436189605761901460431220869026471178146105794252789600089360200963485371408324910599189616457023443860236211419804657495974811016700435647800335341960496809239766311614421810504039975719680312731263581495083550561163971336872957582148769583012551294922894280883597199
Sender's generator for the group is:
3
Sender's private key is:
124161865596736545475872180257413276158
Sender's public key is:
26348168443085206721793219397353997644864553194627246314438201078613883234326432362112043265586150398428558442614339782536235939107904805860514462539057036353021254195836396753058409136899810717127251401312050493274455914758258564495637537084967894708233008864374337557390931606322869822375849936953726735257437496401870481578582511990596335291540316831462649745928196169608961005401659039537266406396219939256826276138995553394692852418041325196981953013991477020980939376361371583173665981303731359304915087735452468595135872474587202250785307306219478547626467495218651932601220067722700387594194835809984844369998
Sender's shared secret key is:
21093143999990752148312413695648824570758887028632314884561865933843735557602491613563078224487331124950094148941447141936256178898529507708765186087292255627512603328719230184097191287594103707538060227810115464339501434728573471082926548024613545180073530225371334786540519082473606356594200745787229896149191402645526263533516301226185349459059775161425383207553676936145267269980734152647845935509878954783230323387631184636543935583627083720559038953531384546311907944394596271999397209274634834850455094198618873541064103892843410931947535296422375053157899457506295346870758919984577340783966014807976149679696

Receiver's 2048-bit prime is:
28976802397353577319062926658877744178503880496815037762628896414753669717663397674152831685113987447038010888674566279621668078832785981730653145652257955384436505204829089716469012016395533554875106781294724763867476051454833198933742421257681393757058316514804910595872009122120896625781392830718028992520516457032443260758033082444235011551763566523528284020737676316315015458821032000655995744718617184214612580369801281243260565786838425247444037623738001452768035685926703086900893696348870553160697781709208153551428931225450904418180607413359613662485532116487800866582022088783037276958617482856698819022911
Receiver's generator for the group is:
11
Receiver's private key is:
156875722145573500478673548695322470331
Receiver's public key is:
5305990774705988595439743046083747673154230769427043607543697107051407404317801002244794588375639295690270480209042376133050302805593217841630760988261264248764102958156115497112768460231324786872032512239501441267597449065705550623115963101625881596190069280767257964743493730559432023214264797869451256868226806226735996064615498686671690337103447954583357906712952627965331629510882805836803177520102499132076649782487058481798962704432767956705897830712176145178743795350120306536358871487880475118557393686645197580694818638462401327844850588347528039763660404253199654188986504787177321430068606278286398687930
Receiver's shared secret key is:
23343431484208419386989305551698199582042408816049631058695451189766926551931740146922786176847907465438728216138879286523678235439179674405276027162264146468256738940719599743470261832690758822520665856060864810227485370267231851129160342119467133368900972545543620233989213405232047072953095569389341643624743854289585338694316799049995269895267333345022123253040715008290321357811034128341902885807243347943393598257341584499155660461822262188727630038361285953193985905333739345220269931167181413507248982944656912023078919598028538088650009124546705320123558799128727428993709018214620778848094810961084502325198

更新

法典:

import random
from sympy import isprime, factorint
from Crypto.Util.number import getPrime

def get_large_prime(bit_length):
    return getPrime(bit_length)

def find_generator(p):
    factors = factorint(p-1)
    
    for g_candidate in range(2, p):
        is_generator = True
        for factor in factors:
            if pow(g_candidate, (p-1)//factor, p) == 1:
                is_generator = False
                break
        if is_generator:
            return g_candidate

def generate_private_key():
    return random.randint(2, 2**128)

def calculate_public_key(generator, private_key, prime):
    return pow(generator, private_key, prime)

def calculate_shared_secret(public_key, private_key, prime):
    return pow(public_key, private_key, prime)

if __name__ == '__main__':
    bit_length = 2048

    # Generate a large prime number and a generator for the sender and receiver
    shared_prime = get_large_prime(bit_length)
    shared_generator = find_generator(shared_prime)

    # Generate private keys for the sender and receiver
    sender_private_key = generate_private_key()
    receiver_private_key = generate_private_key()

    # Calculate public keys for the sender and receiver
    sender_public_key = calculate_public_key(shared_generator, sender_private_key, shared_prime)
    receiver_public_key = calculate_public_key(shared_generator, receiver_private_key, shared_prime)

    # Exchange public keys
    sender_shared_secret = calculate_shared_secret(receiver_public_key, sender_private_key, shared_prime)
    receiver_shared_secret = calculate_shared_secret(sender_public_key, receiver_private_key, shared_prime)

    print(f"Shared {bit_length}-bit prime is:\n{shared_prime}")
    print(f"Shared generator for the group is:\n{shared_generator}")

    print("\nSender:")
    print(f"Sender's private key is:\n{sender_private_key}")
    print(f"Sender's public key is:\n{sender_public_key}")
    print(f"Sender's shared secret key is:\n{sender_shared_secret}\n")

    print("Receiver:")
    print(f"Receiver's private key is:\n{receiver_private_key}")
    print(f"Receiver's public key is:\n{receiver_public_key}")
    print(f"Receiver's shared secret key is:\n{receiver_shared_secret}")

输出:

Shared 2048-bit prime is:
16899290410341716572396500639338421918149765091468487135220652650709698911193474418757406023792601235504593878017964912783586003082034352840947305743950452599705299202335386369810159979082746314315701438407953338440509989481731906394354034704328838084743695911063023400991205526771239045329737675477412673709532659702298110107324090648432821384418970091466270866390118559321732710525699516133920440924736113044514138389852039672800194917535290618917463904117557520264288878064935863360490331640313062243810766671027510945317192096289175427825554353432632036768954025754878652362062305174188873074676394003010853504531
Shared generator for the group is:
2

Sender:
Sender's private key is:
161236650027313735934797782458980097398
Sender's public key is:
7971856757910394108922951410380447364751224558431116344441240025008569568809578524371567650785584853079836013679904085031776514201771382683345840423901705275216751735538909624879047067384474658373938133163700360559276684851018138743535759873536337241654548309524375709506429606126603819710965399401479731940571729124820672836514181922058522610152828493722469528658078715989099251500879802514159818924395688701213151845823566933238007179034142982348268515118507531553386711128180272972335434628463183195287678596482580666652310441361390378828579820453242040992676533511891926767445547313654703605917948041390714911738
Sender's shared secret key is:
4345776665398179044799343721610980787234798487209135354173209491503712546309831652467888319914600859151869628075752433831384942612296891020237206597016560093610165132824430663846221885370221726683912176207896930392347135491714515491502215055785783913364118977827150375472559759151326509391118971817492945430393447337409713925211361397155027022435172253101940752174050568345683174716632785242845755562871066257465827923952933964572371464137817573915046776839798708468670105955214093470129758964911913766734059396662435752842332892030623883795286515827047795450442541860407024929084645119029553347831392682185704360207

Receiver:
Receiver's private key is:
330891456741035173262850158429026798965
Receiver's public key is:
603771668959628491125782128408918656668054975098319487215159658303523807710722236309207304669011604621884194238410396789930817346050513381354992053849834433681672418756998384534593116919848150433507763837487028783135720917510857636536028171370292083444403804042677648138710459990899452095049691411319737270990685588885128903469732586553665334441577860913932724687424243073895842017528350812520453970607109310943508555496637142805726586144585871823727263378505021224591713513712970228332329505202435437737761446777124217039609797611061418578596852296974578391240074183641564334727134093054419432496087964448288537612
Receiver's shared secret key is:
4345776665398179044799343721610980787234798487209135354173209491503712546309831652467888319914600859151869628075752433831384942612296891020237206597016560093610165132824430663846221885370221726683912176207896930392347135491714515491502215055785783913364118977827150375472559759151326509391118971817492945430393447337409713925211361397155027022435172253101940752174050568345683174716632785242845755562871066257465827923952933964572371464137817573915046776839798708468670105955214093470129758964911913766734059396662435752842332892030623883795286515827047795450442541860407024929084645119029553347831392682185704360207

现在,我获得了相同的共享密钥。

谢谢大家抽出时间接受采访。

Python 密码学 sympy diffie-hellman

评论

1赞 President James K. Polk 11/17/2023
这不是香草 Diffie Hellman 的工作方式。首先,发送方和接收方都必须使用相同的素数和相同的基座,或您所说的发生器。另一方面,你对生成器的计算似乎远非正确。您必须知道 p-1 的因式分解才能确定给定元素的阶数。但是,如果 p-1=2p',其中 p' 也是素数,则此计算将大大简化。
1赞 Maarten Bodewes 11/17/2023
pg 是算法的参数;它们需要在两边都相同,否则算法将不起作用。通常我们使用命名参数,例如RFC 3526中的参数
1赞 Frank Yellin 11/17/2023
除非这是为了家庭作业问题,否则你永远不应该实现你自己的 Diffie Hellman。几乎可以保证您的实现将存在某种安全漏洞。仅使用经过专家审查的算法和实现。
0赞 knk 11/17/2023
谢谢大家。我根据您的建议进行了一些修改。我把它放在那里,请告诉我它是否有效。@PresidentJamesK.波尔克

答: 暂无答案