<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Vigenere on Slightwind</title>
    <link>https://slightwind.cn/tags/vigenere/</link>
    <description>Recent content in Vigenere on Slightwind</description>
    <image>
      <title>Slightwind</title>
      <url>https://slightwind.cn/papermod-cover.png</url>
      <link>https://slightwind.cn/papermod-cover.png</link>
    </image>
    <generator>Hugo -- 0.155.3</generator>
    <language>en</language>
    <lastBuildDate>Tue, 16 Nov 2021 09:17:00 +0000</lastBuildDate>
    <atom:link href="https://slightwind.cn/tags/vigenere/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>湖湘杯 2021 Crypto</title>
      <link>https://slightwind.cn/posts/ctf/huxiangbei2021/</link>
      <pubDate>Tue, 16 Nov 2021 09:17:00 +0000</pubDate>
      <guid>https://slightwind.cn/posts/ctf/huxiangbei2021/</guid>
      <description>&lt;h2 id=&#34;hxb-2021-crypto&#34;&gt;hxb 2021 crypto&lt;/h2&gt;
&lt;h3 id=&#34;signin&#34;&gt;signin&lt;/h3&gt;
&lt;p&gt;$n1/n2$ 的连分数展开是对 $q1/q2$ 的一个逼近，所以枚举连分数中的每一项，就可以得到 $q1, q2$ 了，分解之后正常进行 RSA 解密得到 flag。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;from Crypto.Util.number import GCD, inverse, long_to_bytes, isPrime

pk = (1150398070565459492080597718626032792435556703413923483458704675295997646493249759818468321328556510074044954676615760446708253531839417036997811506222349194302791943489195718713797322878586379546657275419261647635859989280700191441312691274285176619391539387875252135478424580680264554294179123254566796890998243909286508189826458854346825493157697201495100628216832191035903848391447704849808577310612723700318670466035077202673373956324725108350230357879374234418393233, 1242678737076048096780023147702514112272319497423818488193557934695583793070332178723043194823444815153743889740338870676093799728875725651036060313223096288606947708155579060628807516053981975820338028456770109640111153719903207363617099371353910243497871090334898522942934052035102902892149792570965804205461900841595290667647854346905445201396273291648968142608158533514391348407631818144116768794595226974831093526512117505486679153727123796834305088741279455621586989)
c1, c2 = (361624030197288323178211941746074961985876772079713896964822566468795093475887773853629454653096485450671233584616088768705417987527877166166213574572987732852155320225332020636386698169212072312758052524652761304795529199864805108000796457423822443871436659548626629448170698048984709740274043050729249408577243328282313593461300703078854044587993248807613713896590402657788194264718603549894361488507629356532718775278399264279359256975688280723740017979438505001819438, 33322989148902718763644384246610630825314206644879155585369541624158380990667828419255828083639294898100922608833810585530801931417726134558845725168047585271855248605561256531342703212030641555260907310067120102069499927711242804407691706542428236208695153618955781372741765233319988193384708525251620506966304554054884590718068210659709406626033891748214407992041364462525367373648910810036622684929049996166651416565651803952838857960054689875755131784246099270581394)
n1, n2 = pk
e = 0x10001

def getRoot(x, n):
    high = 1
    while high ** n &amp;lt;= x: high *= 2
    low = high // 2
    while low &amp;lt; high:
        mid = (low + high) // 2
        if low &amp;lt; mid and mid**n &amp;lt; x:
            low = mid
        elif high &amp;gt; mid and mid**n &amp;gt; x:
            high = mid
        else:
            return mid
    return mid + 1

# https://github.com/pablocelayes/rsa-wiener-attack
def rational_to_contfrac(x, y):
    a = x // y
    pquotients = [a]
    while a * y != x:
        x, y = y, x - a*y
        a = x // y
        pquotients.append(a)
    return pquotients

def convergents_from_contfrac(frac):
    convs = []
    for i in range(len(frac)):
        convs.append(contfrac_to_rational(frac[0:i]))
    return convs

def contfrac_to_rational(frac):
    if len(frac) == 0:
        return (0, 1)
    num = frac[-1]
    denom = 1
    for _ in range(-2, -len(frac) - 1, -1):
        num, denom = frac[_] * num + denom, num
    return (num, denom)

frac = rational_to_contfrac(n1, n2)
convergents = convergents_from_contfrac(frac)

p1, p2 = None, None
for (P1, P2) in convergents:
    gcd1, gcd2 = GCD(P1, n1), GCD(P2, n2)
    p1 = gcd1 if (gcd1.bit_length() &amp;lt;= 128 and isPrime(gcd1)) else p1
    p2 = gcd2 if (gcd2.bit_length() &amp;lt;= 128 and isPrime(gcd2)) else p2

print(f&amp;quot;[+]p1: {p1}&amp;quot;)
print(f&amp;quot;[+]p2: {p2}&amp;quot;)

q1, q2 = getRoot(n1 // p1, 4), getRoot(n2 // p2, 4)

phi1 = (p1 - 1) * (q1 - 1) * q1**3
phi2 = (p2 - 1) * (q2 - 1) * q2**3

m1 = pow(c1, inverse(e, phi1), n1)
m2 = pow(c2, inverse(e, phi2), n2)

flag = (long_to_bytes(m1) + long_to_bytes(m2)).decode()

print(f&amp;quot;[~]flag: {flag}&amp;quot;)

&#39;&#39;&#39;
[+]p1: 181856133933383097933223133658050179553
[+]p2: 196443958511498599913330690975430421229
[~]flag: flag{8ef333ac-21a7-11ec-80f1-00155d83f114}
&#39;&#39;&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;fastot&#34;&gt;fastOT&lt;/h3&gt;
&lt;p&gt;Python 的&lt;code&gt;random&lt;/code&gt;的内部是&lt;strong&gt;MT19937 伪随机数生成器&lt;/strong&gt;，虽然生成的随机数周期很大，但是内部状态（state）很少，仅仅有 624 个，每个值都是 32bit 的。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
