首页 > 解决方案 > Python:我的 Miller-Rabin 实现有什么问题?

问题描述

目前,我尝试从 NIST FIPS186-4 附录 C.3.1 中显示的算法实现 Miller-Rabin-Test。

但是目前我的两个素数的结果似乎并不完美,因为例如在我对代码的所有测试中:

>>> n,e,d = generating_Pairs()
>>> message = 1234567890
>>> cipher = pow(message, e, n)
>>> plain = pow(cipher, d, n)
>>> plain == message
False

(plain 总是一个非常大的 int,比原始消息大)

我的 generate_keys() 函数:

def generating_Pairs():
    p, q = gen_Random_Primes()
    n = p*q
    e = 65537
    phi = (p-1)*(q-1)
    d = inverse(e, phi)
    return(n,e,d)

计算 d 的反函数:

def inverse(e,phi):
    a, b, u = 0, phi, 1
    while(e > 0):
        q = b // e
        e, a, b, u = b%e, u, e, a-q*u
    if(b == 1):
        return a%phi
    else:
        print("Must be co-prime!")

我的 generate_keys() 函数似乎是正确的,因为如果我使用可证明的素数(例如 p = 13th mersenne prime 和 q = 14th mersenne prime,请参见此处),上述测试的结果将是True。我认为我的 is_prime() 函数存在错误,该函数基于 Miller-Rabin-Test ...

from random import randrange
def is_prime(w):
    iteration = 5 #p and q should be 1024 bits => 4 iterations are minimum?

    m = w - 1
    a = 0
    while not(m & 1):
        a += 1
        m >>= 1

    for _ in range(iteration):
        b = randrange(2, w-1)

        while((b <= 1) or b >= w - 1):
            b = randrange(2, w - 1)

        z = power(b, m, w) #see ANN1

        for _ in range(a):
            z = power(z, 2, w) #see ANN1
            if z == 1:
                return False
            if z == w - 1:
                break
    return True

ANN1:我使用的是 power() 函数而不是 math.pow()(edit3:抱歉,内置 pow(x,y [,z]),即 (x**y)%z),因为代码应该在具有特殊 python 版本的特殊系统上运行(由于系统限制),没有 pow(a,b,c)...

也许这个特殊的幂函数会成为问题,但我认为我的 is_prime() 有一个错误,它是我的 gen_Random_Primes() 函数的核心函数,但对于不是的 p 和 q 似乎返回 True真的素数吗?这就是plain == message => False的原因?

但这是我的 power() 因为为了完整性:

def power(x, y, p):
    res = 1
    x = x%p
    while(y > 0):
        if((y & 1) == 1):
            res = (res*x)%p
        y >>= 1
        x = (x*x)%p
    return res

编辑:我的 nlen 应该是 2048 位长 - > p 和 q 的大小是 1024 位(非常大的素数)

编辑2:一个小错误 - 在我的 power() 函数中忘记了返回 res。但在我的实现中,power() 函数有一个返回 res,所以这不会是问题 ;)

edit3:抱歉,内置 pow(x,y [,z]),即 (x**y)%z,而不是 math.pow

编辑4:这里有一些例子:

n = p*q

phi = (p-1)*(q-1)

private_key (用于密码) = (n,e)

public_key(普通)=(n,d)

示例01:################################

p = 153278952386343112861516138830439219958131262572001989611076268355877848523058709999207700485605081468914077929037769261015479227525227452449401011101469723675635614611092243738208719355456013217253135422472477856387471970992716603913394664778594230349851796850845021412801902220705133996887380661818440848317
q = 158966122079667347252293835902427484318353919446383834628309005881872697109397189566089924423596952117031809401859037909351997179049071188790410033650716934063577007590353013796258148845763088248887460202831932907380675412089905177507426652619387129610421611581422746450658896507905016224327948291632998343971
n = 24366160657290937939234153324343152502384001817946624551571122400737379061841645065858899053151158734817070297897852413751169971231673481393316697538906604107269462569082519609906808338138946759303889661330461376990256707586724059857880457741622527522854931069740149809256897665830716836184526115719344743761645933212802480825580807727572342401134038022443167933343106415985609631284326431505534429375684115406275044088979620133778715752680969930614074574261604921123707141539217485547590077450015016094835309620895392345723905466518271070269383228113160497332527751169556561591967414267378951017113422700881402446807
e = 65537
d = 17274963589733526716336965379286208368872091497460548440792233871368258857277723977906646407458617871653269974541492814021611632258243078558052200046504363233595805557316480631623509507961731880072263442392214434906622025135565355711072487121881519123883173127003163415129049134765986039587985739975641762273625715026010738347209341037702876219216462993080200129963155150986046425007682872210677371297597135201485785733365271854554523780116581088384970026628097260935000890283507771219338034919756067218634835147949087816408934549777286243756344974891589231104024074659282336875373169116580764456423226999719026086913
phi = 24366160657290937939234153324343152502384001817946624551571122400737379061841645065858899053151158734817070297897852413751169971231673481393316697538906604107269462569082519609906808338138946759303889661330461376990256707586724059857880457741622527522854931069740149809256897665830716836184526115719344743761333688138336470365466997752839475696857552840424782109103721141747859085651870531940236804466482081820329156758082812963411239346106671289374263529509418263384494519337772228013123209248795914628694713995590981581955758083435649288848561910715179137372254342737288793728506615538768800795898093747429963254520

d 应该是正确的,因为对于这个 e, d, phi:

>>> (e*d)%phi
1

但是,如果您尝试加密(制作密码)和解密(撤消密码 = 普通):

message = 1234567890
cipher = power(message,e,d) #same as (message**e)%n
plain = power(cipher,d,n) #same as (cipher**d)%n

你会得到:

>>> cipher
7582453483123782316642815207511509460123690813093883757865778590854769823444496048630408532746966392966067010239879640641437430367798732703096575691828231449246792228610248734149965734608561945416563715359518516936192024799846436629865250108369647161886815833543979311512965674758113118505287260490159638736268299024213305764769094191211776578538139794602124749434951864660928435041738055064357946181468209321671158821420411181701738699381970454853036275026924447113637686219886313455880197010339064148710566050312637252815539387371754036905714481567541746525837880619907843263703714528916056846821658479428821702799
>>> plain
2506678376199532577786495780354166644277263701374427104991286855439327130392426627706898765559799754136604242869092325064170490643931920526072098326334198460034536727890580557834435895613875615739892723160337739471263384445704979849989265751741515657006179133998272575884880354970790040910244055405007280150155944497462791854983809250394636024022408598995890385001669873486898335192266131038117960572422303140608246905882204766339115796505409973933273130830998154966651370106471194424674487944304554404244102371812455992949145041295591557402607650756918969076755549087347227152938532676219564672872091841940439906823

你可以看到,那个平原真的不是信息

>>> plain == message
False

让我们做第二个例子/测试:EXAMPLE02:###############################

p = 151000448093392138083909177508717203782700741053411977445583547285229153941286337902970666747751598140351035034315356744660640075753463317248127809201201802296279357953239911683665525006800637881313365848486482728096475210446711456467971189292271259825826843971960795144891542895179717280616703652603696895339
q = 148124081383037385391596445248642476004227433435914930913672983646671819235598185424883742197429805844229078255522368361277189556916061601257602591774692685590328750660480818820825397887875014126153510363701871517734836225506065854979355008918136143153161859316761084109149508825851534915899190860012402769611
n = 22366802662260729456956546861488601785938913818506251235759151149363682764610849516896735266633778507381353192212960524484748058148902933375123262193745059835162873665089513061671612181140260714274706430714782809143277901597258645771925028254527786781501499561033344017516390704013770385331368297897961727978672607036696365234991950076062643187019813666393837322094177790596953768668362465889675915765533974409142859879746884071641242665207372602490990036696997084431295929304332268428662030606250672882177696411638288639368218633089155494361214849267709296282062361317108880055193474754723123085711234419765596743129
e = 65537
d = 13160636651999607081788277767867364421157153892751240675547315052897788039869441370074490827348395056252799819920292105912398410338251597064429303091615377532745635812948133156601320001360006311913289124940468051424128087056067380231883866206129369880651552955926695027289425184677037606224700921670830220399194931602658271829767873582989125877075766823913540909325206121964749163064259462915131314311098094522361240734242900774149793450428376068325367076196303741824560961616664817209086260518085294642272283573114246457475475156567633786861244398768202322498025945662612867920320425668328210403728438858957518750153
phi = 22366802662260729456956546861488601785938913818506251235759151149363682764610849516896735266633778507381353192212960524484748058148902933375123262193745059835162873665089513061671612181140260714274706430714782809143277901597258645771925028254527786781501499561033344017516390704013770385331368297897961727978373482507219935711516444453305283507232885491904510413734921259665052795491477942561821506820352570424562746589909158965703413032537847683985259635721102596544687820690611537924171107711575020874710820199449934393536907197136378182913888651057301893303073658028387000801152423033691870889195339907149497078180

检查 d 的条件:

>>>(e*d)%phi
1

让我们对此示例进行加密/解密:

message = 1234567890
cipher = power(message,e,d) #same as (message**e)%n
plain = power(cipher,d,n) #same as (cipher**d)%n

你会得到:

>>> cipher
19582650241671478797736206916151785806793342503887934233292468043928447391216953542528369245042791835732418321140061279441359508294343645916954129769216400129961217152361034874685568300192215242498114226028794719265275556964675603955948790756025759486815304457849055836050730644761707261720362010091500167797282697580948292001704212203516725864235377985907325375001695044383613281561738586886478940910401509320095813715935744827291447691109873641774308205509624953961383224998370369115523043565414869676711449349616974080539090276559658054844048940327159272094930135679435668895885597768311656233633134501875799959945

>>> plain
6083429875214510719927083766713233744592420986316684568290880389711253208169504107321709423820282968116179978192210334710968013237588326260985224812182914293551878626127025285184924521033808922383038422073726589474061901614923932303292881343735655246200763492872615982118360880481263715561005747379043420630222303011824240141556291702645175779056516254627164942441440790263320061469776092449625855913049066614886658724425305130815980340969759725366834527202832142658592646993117009538926737701618299240707475862947345174017146739190658346668982366958034902005777118294631852412541490729616655104422311467398220120569
>>> plain == message
False

现在,我们将使用 PROVABLE PRIMES 测试所有内容,我选择了 p = 13th mersenne prime 和 q = 14th mersenne prime:

示例03:######With#MERSENNE#PRIMES########

p = 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151
q = 531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127
n = 3646154850295011369707131011438711095400799139943170490872585628683549034362552065955809589514611470241298944167703929337528884908857116141935206466329731087514964112054543019336536216107629523597606330154669196064144182472739556974502462402438903115845725630946428943768540714098264727068026730424033578827886916761701429264950573899186177
e = 65537
d = 605309440029444797632079365922351903778944636504290628815687804447518401725202045830587428993072200378798732205389608178468869002370652053408838463061590768976059755211666722868590174546762165023955171158423681809701058604934000382033836393559131564093520170601086332978178762009136501271874027235396379522707933355224417396404416034089473
phi = 3646154850295011369707131011438711095400799139943170490872585628683549034362552065955809589514611470241298944167703929337528884908857116141935206466329731086983826119237775920646948002690363236137403497445736473783306827002900696970344810268812941665073256564401047334962399037297130412119008099533655562939311565101226345855529063752400900

>>> (e*d)%phi
1

>>> message = 1234567890
>>> cipher = pow(message, e, n)
>>> plain = pow(cipher, d, n)
>>> cipher = 3527787294202495847516460093960040111155862778590101142852928060146217450670864190293138429578667938663819181298161737329079067252663099780485504380443854855906571037888470692628813913848572749600751040887103649399418365664020425441281586512839896401702197649288926423242264498276766744058040547340187336760773966010060700622351934331652019
>>> plain
1234567890
>>> plain == message
True

现在,让我们试试第 16 和第 17 梅森素数:EXAMPLE04:######With#MERSENNE#PRIMES########

p = 1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007
q = 446087557183758429571151706402101809886208632412859901111991219963404685792820473369112545269003989026153245931124316702395758705693679364790903497461147071065254193353938124978226307947312410798874869040070279328428810311754844108094878252494866760969586998128982645877596028979171536962503068429617331702184750324583009171832104916050157628886606372145501702225925125224076829605427173573964812995250569412480720738476855293681666712844831190877620606786663862190240118570736831901886479225810414714078935386562497968178729127629594924411960961386713946279899275006954917139758796061223803393537381034666494402951052059047968693255388647930440925104186817009640171764133172418132836351
n = 658416274830184544125027519921443515789888264156074733099244040126213682497714032798116399288176502462829255784525977722903018714434309698108208388664768262754316426220651576623731617882923164117579624827261244506084274371250277849351631679441171018418018498039996472549893150577189302871520311715179730714312181456245097848491669795997289830612988058523968384808822828370900198489249243399165125219244753790779764466236965135793576516193213175061401667388622228362042717054014679032953441034021506856017081062617572351195418505899388715709795992029559042119783423597324707100694064675909238717573058764118893225111602703838080618565401139902143069901117174204252871948846864436771808616432457102844534843857198735242005309073939051433790946726672234643259349535186268571629077937597838801337973092285608744209951533199868228040004432132597073390363357892379997655878857696334892216345070227646749851381208554044940444182864026513709449823489593439017366358869648168238735087593808344484365136284219725233811605331815007424582890821887260682886632543613109252862114326372077785369292570900594814481097443781269562647303671428895764224084402259605109600363098950091998891375812839523613295667253813978434879172781217285652895469194181218343078754501694746598738215243769747956572555989594598180639098344891175879455994652382137038240166358066403475457
e = 65537
d = 334105797271047151981657921517730832371157119074330856217838164677012408641591434986864808806133905517552676051241221220880766442883064579097099015417787407817836444609823288099833966832697449469677098482618977788033303759560236815204203169682707224751050905150039255552119361819964408750709972784839359821706301883041441842767276053766359012570998533260190313947880006413211727740947447067803460706031761174087490228255436052244551636823801781434029233115278710139434099796272520346062523994498058074121550388611165999532399069719243650604162160473244358221089118134071294983607455557349857985437381055885040711267092779938648535194027500626908005136511478177771620221295598221446655310402436746479782368967943153830391704773757455773861050160452401746790867834196061076588076120390140624579927639175546078677218011249954865423538080035612379874054142000812190387918675139826088813202731055651051339403348440263931094983603857618923283552638290258967144154247536313936995282079495778654678503630914818879103007330530120178133686334123351627296777405788745594506415615850210810277691545772909988881340556599596733717401089924014874029987229222036914331526326518454684517757259862612246129598984572912870240390422205211578326598705764422502804258285510188982398306082836846344931332983589484880260309348373229531127293270115611985532798401007828666273
phi = 658416274830184544125027519921443515789888264156074733099244040126213682497714032798116399288176502462829255784525977722903018714434309698108208388664768262754316426220651576623731617882923164117579624827261244506084274371250277849351631679441171018418018498039996472549893150577189302871520311715179730714312181456245097848491669795997289830612988058523968384808822828370900198489249243399165125219244753790779764466236965135793576516193213175061401667388622228362042717054014679032953441034021506856017081062617572351195418505899388715709795992029559042119783423597324707100694064675909238717573058764118893225111602703838080618565401139902143069901117174204252425861289680678342237463250075085820468400139887252603511581541909501414828351105531905619420047668081165948290616571506153659883771881424337363431225547368543782032187128677349306585454844368150965884442693427916237146706380358257245358145214299061139408586133209549295622870737780511845373058603583936928339541786261572218296400422758734811155093559687048536034020967026764962657833198315402334230423388741137414997867176910007275117765698155754484533236565743028710587661566079042375948557880113061241858319026329565154396064729731627098176102570966530887923691946706848615777083090494384632530604575140678340984026032761127934737187086971865040338267351562631185225613687961572868100

>>> (e*d)%phi
1

>>> message = 1234567890
>>> cipher = pow(message,e,n)
>>> plain = pow(cipher, d, n)
>>> cipher
456496826841733818270908304227082534081859737180166510716990603132608133299963062844944786777938246804747496862456284894415366813194701218076961537835930553236745171872139138552898222394380765429166665742337940993686632252985322797309711325449549577191721762092413669164574241208448333134863611775084360543326165001966810743638879340579077493555817807387986451299284100432323322095153193449738193340108996694653981343445907983610632925597419613278322234744442449149930389311418971374507078200795440203783866232507259920822701780626503271754241968747737872417441310189834826470519491444045650181872335299997179988923371195644750576072775817545165334288973701662021461240508380472416824025292141690571188682108619540733596998435122284415140172156977758375901535805389682026731937835429566482533381626946335892833187432334537467818988885690429477550078258412841917692854031969688551447316422564794103804701585262790167250552817617448061370437388807571786103338095535567011877750990827996996417785181236658050169690842830828818599786537294982837492884162936742016732057934481057205481007314702736519071184122573456680456466562972389492586174454504500146300230874944272253606674382312704016456597366616746992611807755165400937216085911729178600772950585314217787447205381014069794060332031079240858890492033777407635220177169518825659433065938177036758094
>>> plain
1234567890
>>> plain == message
True

我希望这是目前足够的例子。

并且 power() 函数工作正常,因为对于每个 pow(a,b,c) == power(a,b,c) 总是True

你可以看到,d 总是计算正确((e*d)%phi == 1,总是 True)

我猜我的 is_prime() 不正确...

标签: pythonkeyrsaprimes

解决方案


我不会读完所有这些。工作量太大了。但这是我的米勒-拉宾素数检查器:

def isPrime(n, k=5): # miller-rabin
    from random import randint
    if n < 2: return False
    for p in [2,3,5,7,11,13,17,19,23,29]:
        if n % p == 0: return n == p
    s, d = 0, n-1
    while d % 2 == 0:
        s, d = s+1, d/2
    for i in range(k):
        x = pow(randint(2, n-1), d, n)
        if x == 1 or x == n-1: continue
        for r in range(1, s):
            x = (x * x) % n
            if x == 1: return False
            if x == n-1: break
        else: return False
    return True

我对前十个素数执行试除法,这消除了大部分候选者,然后对随机基数执行五次强伪素数检查。


推荐阅读