Jekyll2022-12-10T13:49:51+00:00https://blog.cryptohack.org/feed.xmlCryptoHack BlogUpdates about the CryptoHack platform, cryptography news, and CTF writeups.
New Challenges 12/20222022-12-10T00:00:00+00:002022-12-10T00:00:00+00:00https://blog.cryptohack.org/new-challenges-dec-2022<p>Hello CryptoHackers! It’s been a quieter Autumn/Fall for CryptoHack, but we’ve still had a few things going on. And here’s an exciting challenge release.</p>
<h4 id="applied-crypto-study-group">Applied Crypto Study Group</h4>
<p>Chuck Bartowski has been running a reading group for <a href="https://toc.cryptobook.us/">“A Graduate Course in Applied Cryptography”</a>. The study group’s goal is to learn the basics of applied cryptography, with a focus on better understanding of how to argue cryptographic security with proofs. If you’re interested, you can join in on Discord (<a href="https://discord.com/channels/692694094111309866/1028962150380732487">channel link</a>).</p>
<h4 id="backend-improvements">Backend Improvements</h4>
<p>We have been doing some housekeeping on the backend. The CryptoHack platform was forked from <a href="https://github.com/IceCTF/ColdCore">IceCTF’s ColdCore</a> two years ago. IceCTF was only designed for a single CTF, and the data model was not perfect. One of the problems was that usernames were not case-insensitive, which we fixed within a few months of launching.</p>
<p>A worse problem with the data model is that email addresses were not required to be unique. Therefore, thousands of accounts on CH have been registered under duplicate email addresses. In almost all cases these are because people forgot their usernames and registered a new account. The problem is that this meant we couldn’t implement “login by email address” or “reset password by entering email address” features.</p>
<p>Anyway, we finally fixed the problem, and will soon offer those features, which will hopefully put an end to the large number of users who forget their usernames and need admin help. For existing accounts that shared email addresses, we found the most recently active / highest score account and removed the others. In ambiguous cases, we sent an email asking how the player wanted it resolved. Overall this was a lot of work that could have been prevented by getting things right in the first place - a common engineering lesson.</p>
<h3 id="new-challenge-descriptions">New Challenge Descriptions</h3>
<p>These new challenges will be released on Thursday:</p>
<ul>
<li><strong>RSA vs RNG</strong> (RSA): A fun challenge combining RSA and a bad RNG, as you might have guessed from the title. <em>Contributed by jschnei</em></li>
<li><strong>Digestive</strong> (Elliptic Curves): A simple challenge showing a potential pitfall in ECDSA implementation.</li>
<li><strong>Megalomaniac</strong> (Crypto On The Web): A fantastic set of challenges showcasing the recent MEGA attacks. <em>Contributed by $in</em></li>
<li><strong>TLS Part 1</strong> (Crypto On The Web): This rounds out the TLS Part 1 section teaching the cryptographic fundamentals of the TLS protocol.</li>
<li><strong>Learning With Errors</strong> (Post-Quantum): This kicks off a new Post-Quantum category helping you to understand the Kyber and Dilithium algorithms recently selected by NIST. <em>Contributed by the entire country of ireland</em></li>
</ul>
<h3 id="current-scoreboard">Current Scoreboard</h3>
<p><img src="/assets/images/scoreboard_202212.png" alt="CryptoHack Scoreboard 2022/12" /></p>
<p>Congratulations to Neobeo, ndh, and someone12469 for solving the last set of challenges the fastest.</p>hyperrealityHello CryptoHackers! It’s been a quieter Autumn/Fall for CryptoHack, but we’ve still had a few things going on. And here’s an exciting challenge release.Cryptography CTF Archive2022-08-08T00:00:00+00:002022-08-08T00:00:00+00:00https://blog.cryptohack.org/ctf-archive<p>Jack and I met up this weekend to build a feature which a lot of players have requested: a <a href="https://cryptohack.org/challenges/ctf-archive/">cryptography CTF archive</a>.</p>
<p>There are so many CTFs these days and lots of them feature excellent cryptography challenges. We think it’s a shame that so many of these challenges only get hosted and played for a weekend. After the CTF ends, the CTF server usually goes offline, and the original source code may be lost. It’s great when there is a writeup available, but it is often hard to understand the writeup without playing the challenge yourself.</p>
<p>Our objective is to host the best cryptography CTF challenges on our platform forever, or at least as long as economically feasible! A beautiful challenge can be the fastest way to learn a difficult concept and we think archived challenges will complement the rest of the CryptoHack site.</p>
<p>There’s a few considerations we took when implementing this:</p>
<ul>
<li>Since the challenges already appeared in CTFs, there may be public writeups for them.</li>
<li>Therefore, we need to remove the competitive aspect. Archive challenges are worth 0 points, and don’t record first bloods.</li>
<li>It’s helpful to have writeups adjacent to the challenges, so the normal CryptoHack solution functionality is available.</li>
</ul>
<p>The other advantage is that this makes it easier to contribute challenges to be hosted on CryptoHack. In fact, we’re quite proud of how smooth the submission process is:</p>
<ol>
<li>Read the <a href="https://github.com/cryptohack/ctf_archive/blob/main/README.md">README</a> in the <a href="https://github.com/cryptohack/ctf_archive">ctf_archive GitHub repo</a>, which explains how to submit challenges.</li>
<li>The easiest way is to copy one of the existing challenges in the repo, then make your changes:
<ul>
<li>Challenge metadata such as name, original CTF, the flag and the flag format is contained in <code class="language-plaintext highlighter-rouge">description.yml</code></li>
<li>All files in <code class="language-plaintext highlighter-rouge">release_files</code> will be available to the players</li>
<li>The files in <code class="language-plaintext highlighter-rouge">server_files</code> will be what runs on the server for dynamic challenges. The server-side is built using a Dockerfile and always listens on port 1337</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">docker_deploy.py</code> does the magic of templating a <code class="language-plaintext highlighter-rouge">docker-compose.yml</code> file which gives all the dynamic challenges a unique port, adds the flag as an environment variable, and launches them.</li>
<li>Open a pull request against the repo. Once it gets approved and merged by a CryptoHack admin, the challenge will be automatically deployed on CryptoHack.</li>
</ol>
<h3 id="post-quantum-footer">Post-Quantum Footer</h3>
<p>Meanwhile, there has been exciting news in post-quantum cryptography as the Supersingular Isogeny Diffie–Hellman protocol (SIDH), one of the candidates in the NIST post-quantum standardisation competition, has been <a href="https://eprint.iacr.org/2022/975.pdf">completely broken</a>. The researchers’ attack implementation uses the closed-source Magma tool, but Jack and a few others have implemented a <a href="https://github.com/jack4818/Castryck-Decru-SageMath">faster Sage version</a>. More news on this to come!</p>
<p>Behind the scenes top members of the community have been writing post-quantum challenges, especially challenges for understanding Learning With Errors (LWE) cryptosystems which have become the most promising candidates for standardisation. We are looking forward to releasing these soon.</p>hyperrealityJack and I met up this weekend to build a feature which a lot of players have requested: a cryptography CTF archive.New Challenges 06/20222022-06-15T00:00:00+00:002022-06-15T00:00:00+00:00https://blog.cryptohack.org/new-challenges-june-2022<p>Hello CryptoHackers! I’m currently writing this post from Athens, Greece, where we are helping out with the <a href="https://ecsc.eu/icc/">International Cybersecurity Challenge</a>.</p>
<p><img src="/assets/images/athensicc.png" alt="Athens Photo" /></p>
<p>It’s been nearly a year since our last challenge release; some of this has to do with the fact that we’ve been writing challenges for other events. Also Jack now has a baby!</p>
<p>CryptoHack community still has plenty of things going on. For instance just last week jschnei launched an informal reading group on the basics of algebraic number theory on the chat - following this is highly recommended. Overall, the site has gained almost 15000 new users since our last release. It’s awesome and humbling to see so many people continuing to learn cryptography through CryptoHack.</p>
<p>Once again we would like to thank our Patreons for the continued support. Next time we get together for platform development, we plan to use some of the donations to launch a cryptography CTF archive feature where great cryptography challenges from other CTFs and some others we’ve written can be hosted to play.</p>
<p>Next week we’ll be releasing a new set of challenges.</p>
<h3 id="new-challenge-descriptions">New Challenge Descriptions</h3>
<ul>
<li><strong>Beatboxer</strong> (Symmetric Ciphers): The beginning of a much-demanded linear cryptanalysis section, this challenge sees you break a slightly modified version of AES. <em>Contributed by yaumn and Synacktiv</em></li>
<li><strong>Real Curve Crypto</strong> (Elliptic Curves): A difficult and clever challenge for all the ECC junkies. <em>Contributed by jschnei</em></li>
<li><strong>MDFlag</strong> (Hash Functions): A more involved version of MD0 that sees you dig deeper into a famous attack on some hash functions. <em>Contributed by giladk</em></li>
<li><strong>TLS Part 1</strong> (Crypto On The Web): The first part of a practical tutorial on the nuts and bolts of TLS cryptography.</li>
<li><strong>No Way Back Home</strong> (Maths Brainteasers): Another one for fans of modular arithmetic challenges, which combines elements of multiple cryptosystems. <em>Contributed by DCryp7</em></li>
</ul>
<h3 id="current-scoreboard">Current scoreboard</h3>
<p><img src="/assets/images/scoreboard_202206.png" alt="CryptoHack Scoreboard 2022/06" /></p>
<p>Congratulations to hellman, jschnei, and rkm0959 for solving the last set of challenges the fastest.</p>hyperrealityHello CryptoHackers! I’m currently writing this post from Athens, Greece, where we are helping out with the International Cybersecurity Challenge.Announcing Matrix Bridge For CryptoHack Discord Chat2022-02-14T00:00:00+00:002022-02-14T00:00:00+00:00https://blog.cryptohack.org/announcing-matrix-bridge-for-cryptohack-discord-chat<p>CryptoHack chat is based on <a href="https://discord.gg/h9E7cna5pV">Discord</a>, which has worked well for us so far. Discord is free, has a great UI, and has enabled the creation of the awesome <a href="https://github.com/cryptohack/cryptohacker-discord-bot">CryptoHacker bot</a> which links CryptoHack accounts to Discord profiles.</p>
<p>However, there have been some concerns about the use of Discord as our only chat platform. Scams and abuse are rife on Discord, as we documented in a <a href="https://blog.cryptohack.org/crypto-spambots-discord">previous post</a>. We have combated this by enforcing a registration challenge, however this doesn’t stop all spam: real users who have passed the challenge sometimes get their authentication tokens phished, leading to their accounts themselves attempting to phish in as many chat channels and DMs as they can before they get banned.</p>
<p>On a deeper level, many people within the cryptography, privacy, and free software space are against using Discord. It’s a centralised platform that doesn’t have add end-to-end encryption, and is increasingly under pressure to monetise its successful product - probably by selling data to third party advertising companies. CryptoHack chat is public, carefully moderated, and never tends to stray far from engaging technical and academic discussion. We’re not too concerned about Discord for now, but we understand people who would rather avoid it. And apparently Discord now blocks Tor users completely, so those who route their traffic through it can no longer chat.</p>
<p><img src="/assets/images/element-chat.png" alt="Screenshot of Element Chat" /></p>
<p>As such, we have been looking at alternatives so that people can participate in CryptoHack chat through a different medium. For now we’ve setup a self-hosted <a href="https://matrix.org/">Matrix</a> Synapse server which bridges from our Discord. This can be accessed via the Element chat client.</p>
<p>Currently, we are just testing this, and have not yet setup either federation or user registration. We don’t want to make it easy for anonymous accounts on Matrix to abuse the chat, given the amount of effort we’ve put into preventing abuse on Discord. For now this is a trial and we’ll see how it goes.</p>
<p>So those who want to test Matrix will have to email us (or contact by some other means) and we’ll provision you an account. From there, the best way to get started is:</p>
<ol>
<li>Go to <a href="https://app.element.io/">https://app.element.io/</a></li>
<li>Click “Sign In”, edit homeserver to “matrix.cryptohack.org”. Login using your credentials.</li>
<li>You can now explore and send messages to rooms which have been bridged from Discord.</li>
</ol>hyperrealityCryptoHack chat is based on Discord, which has worked well for us so far. Discord is free, has a great UI, and has enabled the creation of the awesome CryptoHacker bot which links CryptoHack accounts to Discord profiles.Real-World Cryptography by David Wong Book Review2022-01-05T00:00:00+00:002022-01-05T00:00:00+00:00https://blog.cryptohack.org/real-world-cryptography-review<p>Best practices in applied cryptography have changed drastically over the last few decades. We know that if a cryptosystem can go wrong, in practice it will go wrong. A classic example is nonce reuse, which a wide number of symmetric ciphers, signature schemes, and authentication protocols are susceptible to (see CryptoHack challenges “ProSign 3” and “Forbidden Fruit”). In response, cryptographers have come up with algorithms such as EdDSA and AES-GCM-SIV which are designed to thwart such common and catastrophic usage errors. Further, in a perfect world developers wouldn’t be touching primitives at all, but would instead be making use of modern high-level libraries with well-documented APIs and a strong set of algorithms under the hood (libsodium, pyca/cryptography, Tink).</p>
<p>Similarly, decades of experience of attacks against TLS, and confidence in algorithms like AES which have stood the test of time, have shown that too much interoperability and cipher agility is bad for secure protocols. Instead we should limit ourselves to the best ciphers that we know of, using authenticated encryption and ephemeral key exchanges, while encrypting and authenticating as much of the handshake as we possibly can - ideas crystallised in TLS 1.3 and taken even further in other modern protocols which completely eradicate the tricky dance of cipher and parameter negotiation.</p>
<p><img src="/assets/images/rwc.jpeg" alt="Picture of the book" /></p>
<p><em>Real-World Cryptography</em> (2021) is full of this accumulated practical wisdom, and is an excellent addition to any cryptography bookshelf. It is fun to read, fills a gap which the existing introductory books on applied cryptography don’t cover, and will remain relevant for a while. It is useful both to cryptography amateurs, as well as motivated generalist programmers who want to know the latest advice on which algorithms and protocols to use without getting lost in the maths.</p>
<p>The book starts with chapters on cryptographic primitives and what they provide. The focus is very much on state-of-the-art implementations of those primitives. For instance, the chapter on symmetric encryption is actually titled “Authenticated encryption”. After a high-level overview of AES, and a section on what is wrong with ECB and CBC block cipher modes, the chapter introduces the concept of authenticated encryption with associated data (AEAD) and dedicates the most space to describing AES-GCM and ChaCha20-Poly1305. Finally, the chapter ends with paragraphs on the specific challenges posed by key wrapping, disk encryption, and database encryption. The message is clear: if you need to encrypt data, then unless you’re dealing with a special case like disk encryption, AEAD ciphers are what your application should be using under the hood.</p>
<p>The second part of the book looks at protocols, “the recipes of cryptography”. The chapters on secure transport and end-to-end encryption dedicate the vast majority of room to TLS 1.3, the Noise protocol, and the Signal protocol. Next are intriguing chapters on hardware cryptography, cryptocurrency (Wong believes this is the first general cryptography book with such a chapter), post-quantum cryptography, and next-generation cryptography (MPCs, ZKPs, and FHE). I don’t know of any other cryptography book with such clear and intuitive introductions to these fascinating yet intimidating areas. Finally, the book concludes with a chapter on why cryptography goes wrong, which mentions resources including CryptoPals and CryptoHack (yay!).</p>
<p>Overall I felt the second half of the book was weaker than the first in a few places. The end-to-end encryption chapter could have been structured better: while I don’t disagree with the criticism the author has for PGP, the chapter rushes to describe the flaws of PGP before fully explaining what it is, and never mentions its more successful use-case in open source package distribution. The description of the Signal protocol that comes after is more intensely technical than other parts of the book and doesn’t follow as well as it could from the PGP section. I didn’t like that the cryptocurrency chapter had a section on Facebook’s Diem blockchain; for a second cryptocurrency after the Bitcoin section, a smart contract cryptocurrency such as Ethereum would have been a more natural choice.</p>
<p>It’s worth briefly comparing <em>Real-World Cryptography</em> to a couple other books in the field. The last applied cryptography book that I imagine a lot of developers would have read is Ferguson and Schneier’s <em>Cryptography Engineering</em> (2010). While still a good read, it’s now dated and even when it was published, contained large omissions such as any coverage of elliptic curve cryptography.</p>
<p><em>Real-World Cryptography</em> is quite a lot less formal than <em>Cryptography Engineering</em>, for instance it doesn’t have much notation or even references. That’s not a disadvantage, in fact the style of <em>Real-World Cryptography</em> is very readable and intuitive, however those who prefer a highly rigorous approach might find it harder to get along with. Due to the breadth of topics covered, depth is necessarily sacrificed in a lot of places. <em>Real-World Cryptography</em> distinguishes itself from <em>Cryptography Engineering</em> and other solid reads like <em>Serious Cryptography</em> (2017) by avoiding theoretical cryptography and mathematics even more than those books do, and using the extra space to surface a whole bunch of practical concerns and protocols which you might only otherwise learn about by tracking down an assortment of papers and blog posts. As Wong says in the preface, “this is what I would have written to my past self in order to prepare him for the real world”. And there’s value in this book for a large audience; even those who already know a lot about cryptography will learn something from this wide-ranging tour of the field. I would recommend it to anyone who is curious about what real-world cryptography looks like in 2022 and what it could look like in the future.</p>hyperrealityBest practices in applied cryptography have changed drastically over the last few decades. We know that if a cryptosystem can go wrong, in practice it will go wrong. A classic example is nonce reuse, which a wide number of symmetric ciphers, signature schemes, and authentication protocols are susceptible to (see CryptoHack challenges “ProSign 3” and “Forbidden Fruit”). In response, cryptographers have come up with algorithms such as EdDSA and AES-GCM-SIV which are designed to thwart such common and catastrophic usage errors. Further, in a perfect world developers wouldn’t be touching primitives at all, but would instead be making use of modern high-level libraries with well-documented APIs and a strong set of algorithms under the hood (libsodium, pyca/cryptography, Tink).CSAW Quals 2021 | Bits2021-09-18T00:00:00+00:002021-09-18T00:00:00+00:00https://blog.cryptohack.org/csaw-2021-bits<p>CryptoHack was asked to make some challenges for CSAW 2021 and Bits was our submission for the qualifiers, written by Robin and Jack. For those who qualified for the finals, you’ll have the chance to solve a few more CryptoHack challenges, but for now, we wanted to go through Bits, explain some potential solutions and some cover a few interesting things we learnt when building the challenge itself.</p>
<!--more-->
<p>Let’s kick off with the puzzle itself, which was given to CSAW players as an interactive challenge with the following source code</p>
<h3 id="challenge">Challenge</h3>
<blockquote>
<p>I wrote this oracle in rust so that it can’t sue companies over java stuff</p>
</blockquote>
<h4 id="source">Source</h4>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="n">BufRead</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">getrandom</span><span class="p">::</span><span class="n">getrandom</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">rug</span><span class="p">::{</span>
<span class="nn">rand</span><span class="p">::{</span><span class="n">RandGen</span><span class="p">,</span><span class="n">RandState</span><span class="p">},</span>
<span class="n">Integer</span>
<span class="p">};</span>
<span class="k">use</span> <span class="nn">sha2</span><span class="p">::{</span><span class="n">Sha256</span><span class="p">,</span><span class="n">Digest</span><span class="p">};</span>
<span class="k">use</span> <span class="nn">aes</span><span class="p">::{</span><span class="n">Aes256</span><span class="p">,</span><span class="n">Aes256Ctr</span><span class="p">,</span><span class="n">NewBlockCipher</span><span class="p">,</span><span class="nn">cipher</span><span class="p">::{</span><span class="n">FromBlockCipher</span><span class="p">,</span><span class="n">StreamCipher</span><span class="p">}};</span>
<span class="k">use</span> <span class="nn">generic_array</span><span class="p">::</span><span class="n">GenericArray</span><span class="p">;</span>
<span class="c">// Secret sauce</span>
<span class="c">// N = p*q; p ≡ q ≡ 3 (mod 4); p, q prime</span>
<span class="k">use</span> <span class="nn">hardcore</span><span class="p">::{</span><span class="n">dlog</span><span class="p">,</span> <span class="n">N</span><span class="p">,</span> <span class="n">G</span><span class="p">,</span> <span class="n">ORDER</span><span class="p">,</span> <span class="n">FLAG</span><span class="p">};</span>
<span class="k">struct</span> <span class="n">SystemRandom</span><span class="p">;</span>
<span class="k">impl</span> <span class="n">RandGen</span> <span class="k">for</span> <span class="n">SystemRandom</span> <span class="p">{</span>
<span class="k">fn</span> <span class="nf">gen</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="nb">u32</span> <span class="p">{</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">buf</span><span class="p">:</span> <span class="p">[</span><span class="nb">u8</span><span class="p">;</span> <span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">;</span> <span class="mi">4</span><span class="p">];</span>
<span class="k">let</span> <span class="mi">_</span> <span class="o">=</span> <span class="nf">getrandom</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">buf</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="p">((</span><span class="n">buf</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">as</span> <span class="nb">u32</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">24</span><span class="p">)</span> <span class="p">|</span> <span class="p">((</span><span class="n">buf</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">as</span> <span class="nb">u32</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">16</span><span class="p">)</span> <span class="p">|</span> <span class="p">((</span><span class="n">buf</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">as</span> <span class="nb">u32</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">8</span><span class="p">)</span> <span class="p">|</span> <span class="p">(</span><span class="n">buf</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="k">as</span> <span class="nb">u32</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">encrypt_flag</span><span class="p">(</span><span class="n">shared</span><span class="p">:</span> <span class="n">Integer</span><span class="p">)</span> <span class="p">{</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">hasher</span> <span class="o">=</span> <span class="nn">Sha256</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="n">hasher</span><span class="nf">.update</span><span class="p">(</span><span class="n">shared</span><span class="nf">.to_string</span><span class="p">());</span>
<span class="k">let</span> <span class="n">key</span> <span class="o">=</span> <span class="n">hasher</span><span class="nf">.finalize</span><span class="p">();</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">cipher</span> <span class="o">=</span> <span class="nn">Aes256Ctr</span><span class="p">::</span><span class="nf">from_block_cipher</span><span class="p">(</span>
<span class="nn">Aes256</span><span class="p">::</span><span class="nf">new_from_slice</span><span class="p">(</span><span class="o">&</span><span class="n">key</span><span class="nf">.as_slice</span><span class="p">())</span><span class="nf">.unwrap</span><span class="p">(),</span>
<span class="o">&</span><span class="nn">GenericArray</span><span class="p">::</span><span class="nf">clone_from_slice</span><span class="p">(</span><span class="o">&</span><span class="p">[</span><span class="mi">0</span><span class="p">;</span> <span class="mi">16</span><span class="p">])</span>
<span class="p">);</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">flag</span> <span class="o">=</span> <span class="n">FLAG</span><span class="nf">.clone</span><span class="p">();</span>
<span class="n">cipher</span><span class="nf">.apply_keystream</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">flag</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"FLAG = {}"</span><span class="p">,</span> <span class="n">flag</span><span class="nf">.iter</span><span class="p">()</span><span class="nf">.map</span><span class="p">(|</span><span class="n">c</span><span class="p">|</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{:02x}"</span><span class="p">,</span> <span class="n">c</span><span class="p">))</span><span class="py">.collect</span><span class="p">::</span><span class="o"><</span><span class="nb">String</span><span class="o">></span><span class="p">());</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"+++++++++++++++++++++++++++++++++++++++++++++++</span><span class="se">\n</span><span class="err">\</span><span class="s">
+ I hear there's a mythical oracle at Delphi. +</span><span class="se">\n</span><span class="err">\</span><span class="s">
+++++++++++++++++++++++++++++++++++++++++++++++</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">sysrng</span> <span class="o">=</span> <span class="n">SystemRandom</span><span class="p">;</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">rnd</span> <span class="o">=</span> <span class="nn">RandState</span><span class="p">::</span><span class="nf">new_custom</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">sysrng</span><span class="p">);</span>
<span class="k">let</span> <span class="n">d</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">ORDER</span><span class="p">)</span><span class="nf">.random_below</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">rnd</span><span class="p">);</span>
<span class="k">let</span> <span class="n">publ</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">G</span><span class="p">)</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">d</span><span class="p">,</span> <span class="o">&*</span><span class="n">N</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="n">nbits</span> <span class="o">=</span> <span class="n">ORDER</span><span class="nf">.significant_bits</span><span class="p">();</span>
<span class="k">let</span> <span class="n">alice</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">G</span><span class="p">)</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">ORDER</span><span class="p">)</span><span class="nf">.random_below</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">rnd</span><span class="p">),</span> <span class="o">&*</span><span class="n">N</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"N = {}</span><span class="se">\n</span><span class="s">G = {}</span><span class="se">\n</span><span class="s">publ = {}</span><span class="se">\n</span><span class="s">alice = {}</span><span class="se">\n</span><span class="s">nbits = {}"</span><span class="p">,</span>
<span class="o">*</span><span class="n">N</span><span class="p">,</span>
<span class="o">*</span><span class="n">G</span><span class="p">,</span>
<span class="n">publ</span><span class="p">,</span>
<span class="n">alice</span><span class="p">,</span>
<span class="n">nbits</span><span class="p">);</span>
<span class="nf">encrypt_flag</span><span class="p">(</span><span class="n">alice</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">d</span><span class="p">,</span> <span class="o">&</span><span class="n">N</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">());</span>
<span class="k">for</span> <span class="n">line</span> <span class="n">in</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="nf">stdin</span><span class="p">()</span><span class="nf">.lock</span><span class="p">()</span><span class="nf">.lines</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">input</span> <span class="o">=</span> <span class="n">line</span><span class="nf">.unwrap</span><span class="p">()</span><span class="py">.parse</span><span class="p">::</span><span class="o"><</span><span class="n">Integer</span><span class="o">></span><span class="p">()</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">match</span> <span class="nf">dlog</span><span class="p">(</span><span class="n">input</span><span class="nf">.clone</span><span class="p">())</span> <span class="p">{</span>
<span class="nb">None</span> <span class="k">=></span> <span class="nd">println!</span><span class="p">(</span><span class="s">"-1"</span><span class="p">),</span>
<span class="nf">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">=></span> <span class="p">{</span>
<span class="k">assert</span><span class="o">!</span><span class="p">(</span><span class="n">G</span><span class="nf">.clone</span><span class="p">()</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">x</span><span class="p">,</span> <span class="o">&*</span><span class="n">N</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span> <span class="o">==</span> <span class="n">input</span> <span class="o">%</span> <span class="o">&*</span><span class="n">N</span><span class="p">);</span>
<span class="k">assert</span><span class="o">!</span><span class="p">(</span><span class="n">x</span> <span class="o"><</span> <span class="o">*</span><span class="n">ORDER</span><span class="p">);</span>
<span class="k">assert</span><span class="o">!</span><span class="p">(</span><span class="n">x</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">);</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="n">x</span><span class="nf">.get_bit</span><span class="p">(</span><span class="n">nbits</span> <span class="o">-</span> <span class="mi">123</span><span class="p">)</span> <span class="k">as</span> <span class="nb">i32</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="overview-of-the-challenge">Overview of the challenge</h2>
<p>Upon inspection of the source code, we see that we can obtain an encrypted version of the flag, encrypted with the shared secret of a Diffie-Hellman key exchange. What’s special about this key exchange, is that instead of the usual $\mathbb{F}_p^\star$, we’re working in the group $(\mathbb{Z}/n\mathbb{Z})^\star$ with</p>
\[\begin{align}
n &= pq\newline p &\equiv 3 \pmod 4\newline
q &\equiv 3 \pmod 4\newline
p, q &\text{ prime},
\end{align}\]
<p>which implies among other things that there is no element $g$ that generates the entire group.</p>
<p>Furthermore, the challenge provides us with an oracle that reveals the $123^{\textrm{rd}}$ MSB to us. While later we will cover exactly how the group is backdoored such that this oracle can even exist — and how this backdoor can be abused to solved the challenge — we will cover a <em>proper</em> solution, that does not depend on the practical existence of this oracle. This solution serves as a proof by construction of the bit-hardness of the $123^{\textrm{rd}}$ MSB for the discrete log in the group $(\mathbb{Z}/n\mathbb{Z})^\star$, something that can be easily extended to most other bits.</p>
<h3 id="challenge-plumbing">Challenge plumbing</h3>
<p>Let’s start by implementing the communication we will need with the server, and some other utility functions:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">os</span><span class="p">;</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">"PWNLIB_NOTERM"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"1"</span> <span class="c1"># for tqdm this time
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">tqdm</span>
<span class="kn">from</span> <span class="nn">json</span> <span class="kn">import</span> <span class="n">loads</span><span class="p">,</span> <span class="n">dumps</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">from</span> <span class="nn">Crypto.PublicKey</span> <span class="kn">import</span> <span class="n">RSA</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.Padding</span> <span class="kn">import</span> <span class="n">unpad</span>
<span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="n">GF</span><span class="p">,</span> <span class="n">discrete_log</span><span class="p">,</span> <span class="n">crt</span><span class="p">,</span> <span class="n">sqrt</span><span class="p">,</span> <span class="n">ZZ</span>
<span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="n">LOCAL</span><span class="p">:</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">process</span><span class="p">([</span><span class="s">"./target/release/hardcore"</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="n">args</span><span class="p">.</span><span class="n">HOST</span><span class="p">,</span> <span class="n">args</span><span class="p">.</span><span class="n">PORT</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"N = "</span><span class="p">)</span>
<span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
<span class="n">g</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">pub</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">alice</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">nbits</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">FLAG</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="n">strip</span><span class="p">().</span><span class="n">decode</span><span class="p">())</span>
<span class="c1"># Convert so that LSB is at index 0
</span><span class="n">index</span> <span class="o">=</span> <span class="n">nbits</span> <span class="o">-</span> <span class="mi">123</span>
<span class="c1"># Once we obtain the private key, we can decrypt the flag
</span><span class="k">def</span> <span class="nf">dec</span><span class="p">(</span><span class="n">d</span><span class="p">):</span>
<span class="n">shared</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">alice</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">sha256</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">shared</span><span class="p">).</span><span class="n">encode</span><span class="p">()).</span><span class="n">digest</span><span class="p">()</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CTR</span><span class="p">,</span> <span class="n">nonce</span><span class="o">=</span><span class="nb">bytes</span><span class="p">(</span><span class="mi">12</span><span class="p">))</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">cipher</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">).</span><span class="n">decode</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="c1"># Query the oracle for point P, by default fail hard
# if it's not a point generated by `g`
</span><span class="k">def</span> <span class="nf">has</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">fail</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">P</span><span class="p">).</span><span class="n">encode</span><span class="p">())</span>
<span class="n">res</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">())</span>
<span class="k">if</span> <span class="n">fail</span><span class="p">:</span>
<span class="k">assert</span> <span class="n">res</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span>
<span class="k">return</span> <span class="p">{</span><span class="mi">1</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="mi">0</span><span class="p">:</span> <span class="bp">False</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span> <span class="bp">None</span><span class="p">}[</span><span class="n">res</span><span class="p">]</span>
</code></pre></div></div>
<h3 id="recovering-low-bits">Recovering low bits</h3>
<p>Given the public information $g$, $g^d \mod n$ and the challenge oracle, we will first proceed to recover all less significant bits than the one the oracle can reveal to us. When the number of more significant bits would be lower than it is in this challenge (or when you’re willing to spend plenty of CPU time on this challenge), this would be sufficient to mount an attack with e.g. the baby-step-giant-step algorithm to retrieve the rest of the private key $d$ in $\tilde{\mathcal{O}}(\sqrt{2^\ell})$, where $\ell$ represents the number of more significant bits.</p>
<p>One of the key observations is that given $g^d$ we can easily compute $g^{d + a}$ and $g^{d - a}$, without any knowledge of $d$. In particular this allows us to set a bit we know is unset, or clear it when we know it is set.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">setbit</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">P</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="mi">1</span> <span class="o"><<</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">))</span> <span class="o">%</span> <span class="n">n</span>
<span class="k">def</span> <span class="nf">clearbit</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
<span class="c1"># requires modern enough python 3 for the negative
</span> <span class="c1"># exponent, use modular inverse otherwise
</span> <span class="k">return</span> <span class="p">(</span><span class="n">P</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="o">-</span><span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="n">i</span><span class="p">),</span> <span class="n">n</span><span class="p">))</span> <span class="o">%</span> <span class="n">n</span>
</code></pre></div></div>
<p>Then, noting how (binary) addition works with carry, we see that adding a single bit at position $i$, will change a bit sequence of the form <code class="language-plaintext highlighter-rouge">011..1</code> (with the least significant $1$ at position $i$), into <code class="language-plaintext highlighter-rouge">100...0</code> without changing any other bits. So, when we arrange our input $g^{d’}$ into the oracle such that position $123$ contains a $0$, and every bit from there until the position $\alpha$ we’re looking at contains a $1$ (we can easily do this inductively by first determining the bit and setting it when needed), we know that the bit at $\alpha$ contains a one if and only if the oracle responds with $1$ for the input $g^{d’ + 2^\alpha}$.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Quick and dirty global variable
</span><span class="n">d</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">set</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
<span class="k">global</span> <span class="n">d</span>
<span class="n">d</span> <span class="o">|=</span> <span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="n">i</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">right_bits</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
<span class="k">if</span> <span class="n">has</span><span class="p">(</span><span class="n">P</span><span class="p">):</span>
<span class="nb">set</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">clearbit</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">tqdm</span><span class="p">.</span><span class="n">trange</span><span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="k">if</span> <span class="n">has</span><span class="p">(</span><span class="n">setbit</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">j</span><span class="p">)):</span>
<span class="nb">set</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">setbit</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span>
<span class="k">return</span> <span class="n">P</span>
</code></pre></div></div>
<h3 id="lets-factor">Let’s factor</h3>
<p>At this point, we’d like to be able to somehow <em>slide</em> the more significant bits into the view the oracle offers us. If we could take a square root mod $n$, and distinguish whether it is the <em>principal square root</em>, i.e. the one that corresponds to $g^{\frac{d}{2}}$, this would be achievable. Unfortunately, taking a square root mod $n$ turns out to be as hard as factoring $n$ when $n$ is not a prime power.</p>
<p>Therefore, we will first apply our newfound power to find a good amount of least significant bits to factor $n$, before we continue down that road.</p>
<p>By Carmichael’s theorem, we know that $g^{\lambda(n)} \equiv 1 \pmod n$ and thus we can see that $g^{n} \equiv g^{\lambda(n)} g^{n - \lambda(n)} \equiv g^{n - \lambda(n)} \pmod n$. We know that $n = pq$, so</p>
\[\lambda(n) = \mathrm{lcm}(p - 1, q - 1) = \frac{n - p - q + 1}{2},\]
<p>under the minor assumption that $\gcd(p - 1, q - 1) = 2$. When we now assume that $p$ and $q$ are balanced enough — and otherwise factoring $n$ would be easier with the elliptic curve method — it follows that $n - \lambda(n) < 2^{1024-123}$ and can entirely be revealed with our <code class="language-plaintext highlighter-rouge">right_bits</code> method discussed above. From there, we can factor $n$ by the usual techniques, since we have 2 independent equations in 2 variables.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.PublicKey</span> <span class="kn">import</span> <span class="n">RSA</span>
<span class="n">right_bits</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">n</span><span class="p">),</span> <span class="n">index</span><span class="p">)</span>
<span class="n">order</span> <span class="o">=</span> <span class="n">n</span> <span class="o">-</span> <span class="n">d</span>
<span class="k">assert</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">order</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
<span class="c1"># Ugly hack so I don't have to implement the factorization myself :)
</span><span class="n">p</span> <span class="o">=</span> <span class="n">RSA</span><span class="p">.</span><span class="n">construct</span><span class="p">((</span><span class="n">n</span><span class="p">,</span> <span class="mh">0x10001</span><span class="p">,</span> <span class="nb">pow</span><span class="p">(</span><span class="mh">0x10001</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">order</span><span class="p">))).</span><span class="n">p</span>
<span class="k">assert</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">n</span> <span class="o">!=</span> <span class="n">p</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="n">p</span>
<span class="c1"># Reset d, don't reuse the stuff from `n - order`
</span><span class="n">d</span> <span class="o">=</span> <span class="mi">0</span>
</code></pre></div></div>
<h3 id="a-first-solution">A first solution</h3>
<p>Now that we’ve successfully factored $n$, we are actually already able to find the secret $d$ without explicitely recovering the high bits as we planned to initially. However, this is only due to the backdoor in the discrete log problem that had to be introduced to allow the construction of this bit oracle (recall that this entire challenge is essentially a proof of the bit-hardness of the discrete log, so it would not make sense to have an oracle without some weakness introduced into the group).</p>
<p>We constructed a backdoor-DLP group, in the following way: we choose two primes $p$ and $q$ such that $p-1$ and $q - 1$ are both $B$-smooth, for some appropriate bound $B$. Knowing the factorisation of $n = pq$, and additionally the factorization of $p-1$ and $q - 1$, we can calculate a discrete log in time $\tilde{\mathcal{O}}\left(\sqrt{B}\frac{\log p}{\log B}\right)$.</p>
<p>To see this, observe that we can calculate the discrete log mod $p$ and $q$ individually with the Pohlig-Hellman algorithm, which runs in time $\tilde{\mathcal{O}}(\sqrt{B})$ per prime factor, and then combine these two results with the chinese remainder theorem.</p>
<p>Introducing this weakness to the DLP additionally opens up $n$ to Pollard’s $p - 1$ factoring algorithm. This generally allows us to factor in time $\tilde{\mathcal{O}}(B \log^2(n))$, if $p - 1$ is <em>powersmooth</em>.</p>
<p>To avoid the unintended solution (🧀) of $p-1$ factoring without the lower bits known, we introduced an extra countermeasure into our construction of the backdoor by making $p - 1 = 2p_0^{16}p_1$ (and similarly for $q - 1$).
This means that either of two things need to happen in order to successfully factor with a pollard $p - 1$ variant (within reasonable time):</p>
<ul>
<li>Either a player needs to guess this fact, enumerating primes up to $B = 2^{30}$, but taking powers up to $B^{16}$ or higher;</li>
<li>or applying the variant where $B’!$ is used for $B’ = 16B$ as an exponent, leading to a seriously higher running time.</li>
</ul>
<p>Given that we have at least a quadratic advantage in our discrete logarithm compared to factoring, and including some extra safety measures, we deemed this approach safe enough for a CTF challenge! Another potential extra mitigation could consist of adding some factor that is not $B$-smooth to each of $p - 1$ and $q - 1$ that is not used by the subgroup generated by $g$. That gives us a hidden subgroup generated by $g$ without the ability to factor $n$ with Pollard’s $p - 1$ method anymore, but this order is necessarily significantly smaller than $n$, which could potentially break the factoring approach outlined earlier, and is in our opinion less satisfying to have than a maximal subgroup of size $\frac{\varphi(n)}{2}$.</p>
<p>Given that the trapdoor has now been found by our solution-in-progress, we can apply the Pohlig-Hellman approach ourselves, and solve the challenge. Unfortunately, we have to rely on a technicality of the challenge implementation, so it is not quite satisfying yet.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="n">GF</span><span class="p">,</span> <span class="n">discrete_log</span><span class="p">,</span> <span class="n">crt</span><span class="p">,</span> <span class="n">sqrt</span><span class="p">,</span> <span class="n">ZZ</span>
<span class="n">dl_p</span> <span class="o">=</span> <span class="n">discrete_log</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">pub</span><span class="p">),</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">g</span><span class="p">))</span>
<span class="n">dl_q</span> <span class="o">=</span> <span class="n">discrete_log</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">)(</span><span class="n">pub</span><span class="p">),</span> <span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">)(</span><span class="n">g</span><span class="p">))</span>
<span class="n">private</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">crt</span><span class="p">([</span><span class="n">dl_p</span><span class="p">,</span> <span class="n">dl_q</span><span class="p">],</span> <span class="p">[</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">q</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span>
<span class="k">print</span><span class="p">(</span><span class="n">dec</span><span class="p">(</span><span class="n">private</span><span class="p">))</span>
</code></pre></div></div>
<h3 id="recovering-high-bits">Recovering high bits</h3>
<p>Returning to the full solution that doesn’t depend on implementation details, we again start looking at finding principal square roots of $g^d$.</p>
<p>We want to find <em>the</em> square root of $g^d$ that corresponds to $g^{\frac{d}{2}}$ (this also still requires setting the LSB to $0$ to ensure $g^d$ is actually a quadratic residue). To get started, we first make sure we can find all modular square roots of $g^d$ and afterwards, we will use our established abilities to verify which of these is the principal square root. Once we have identified that, it’s only a matter of “shifting” the current $d$ to the right, and repeating these steps until all high bits have been found.</p>
<p>To find square roots $\mod pq$, we can find the square roots $\mod p$ and $\mod q$ individually, and combine them pairwise with the chinese remainder theorem. Because $(\mathbb{Z}/n\mathbb{Z})^*$ is not a cyclic group, and $g$ only generates half of the elements in the group, only 2 out of the 4 possible square roots will have a discrete log. To identify which of those two corresponds to the shift of $d$, we can use our old approach to identify if everything to the right of the oracle bit is still set to $1$, which will only be preserved for the square root where a shift happens.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">left_bits</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">idx</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">tqdm</span><span class="p">.</span><span class="n">trange</span><span class="p">(</span><span class="n">idx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nbits</span><span class="p">):</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">setbit</span><span class="p">(</span><span class="n">clearbit</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">idx</span><span class="p">)</span> <span class="c1"># Clear LSB -> make square; make the current bit part of the 1 sled before shifting
</span> <span class="k">for</span> <span class="n">ss</span> <span class="ow">in</span> <span class="p">[</span><span class="n">crt</span><span class="p">([</span><span class="n">ZZ</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">y</span><span class="p">)],</span> <span class="p">[</span><span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">])</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sqrt</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">P</span><span class="p">),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">sqrt</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">)(</span><span class="n">P</span><span class="p">),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)]:</span>
<span class="n">candidate_bit</span> <span class="o">=</span> <span class="n">has</span><span class="p">(</span><span class="n">ss</span><span class="p">,</span> <span class="n">fail</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
<span class="k">if</span> <span class="n">candidate_bit</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">continue</span>
<span class="k">if</span> <span class="n">candidate_bit</span><span class="p">:</span>
<span class="n">Q</span> <span class="o">=</span> <span class="n">clearbit</span><span class="p">(</span><span class="n">ss</span><span class="p">,</span> <span class="n">idx</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">Q</span> <span class="o">=</span> <span class="n">ss</span>
<span class="k">if</span> <span class="n">has</span><span class="p">(</span><span class="n">setbit</span><span class="p">(</span><span class="n">Q</span><span class="p">,</span> <span class="mi">0</span><span class="p">)):</span> <span class="c1"># see if it flows all the way over the 1s
</span> <span class="n">P</span> <span class="o">=</span> <span class="n">Q</span>
<span class="k">if</span> <span class="n">candidate_bit</span><span class="p">:</span>
<span class="nb">set</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="nb">RuntimeError</span><span class="p">(</span><span class="s">"Could not find a good square root"</span><span class="p">)</span>
</code></pre></div></div>
<p>If we had less missing bits, an alternative approach to recovering the high bits — not depending on the factorization of $n$ — could be constructed from a variant of Shanks’ Baby-Step Giant-Step algorithm, in time $\tilde{\mathcal{O}}\left(2^{\mathsf{index}/2}\right)$.</p>
<h3 id="putting-it-all-together">Putting it all together</h3>
<p>With all prerequisites out of the way, it’s simply a matter of applying it to find the full solution.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">d</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">right_bits</span><span class="p">(</span><span class="n">pub</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span>
<span class="n">left_bits</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">dec</span><span class="p">(</span><span class="n">d</span><span class="p">))</span>
</code></pre></div></div>
<h3 id="one-potential-problem">One potential problem</h3>
<p>One thing this writeup neglected so far is the possibility for <code class="language-plaintext highlighter-rouge">right_bits</code> to go wrong. When $d’ \ge |g|$, we would see a reduction mod $|g|$, and get invalid results. This doesn’t happen in this case because it becomes unlikely that this is triggered the farther to the right the oracle lies. Should this case happen nonetheless — and we can detect this by noticing that the discrete log is incorrect — this would imply that the most significant bit of $d$ has to be $1$, and as such we can set it to $0$, repeat our algorithm, and set the bit back to $1$ in our final result. This modification is then guaranteed not to have this wrap around problem.</p>
<h3 id="backdoor-and-preventing-easy-factorization">Backdoor and preventing easy factorization</h3>
<p>As discussed above, to build an oracle which could solve the discrete log problem in a reasonable amount of time we needed to weaken the problem by carefully picking the primes $p,q$. By allowing $(p-1)$ and $(q-1)$ to have many small factors, we could solve the discrete log $g^x \pmod p$ and $g^x \pmod q$ using Pohlig-Hellman and Baby-Step-Giant-Step, then combine the results using the Chinese remainder theorem. As mentioned in the main text, these small factors weakened the challenge by allowing Pollard’s $(p-1)$ factoring algorithm to factor $n$ without using $\lambda(n)$ at all. We attempted to protect against this by allowing $p = 2 \cdot p_0^{16} \cdot p_1$. The repeated factors complicated the factoring algorithm but speed up the discrete log as we can reuse our baby steps.</p>
<p>Ultimately, we chose to make the challenge in rust to enjoy the moderate speed up when compared with python, however the total time save (roughly a factor of two) was much smaller than we initally anticipated. We believe this ultimately comes down to the <code class="language-plaintext highlighter-rouge">rug</code> crate for rust and <code class="language-plaintext highlighter-rouge">gmpy2</code> in python3 both calling <code class="language-plaintext highlighter-rouge">GMP</code> in C. Using python <code class="language-plaintext highlighter-rouge">int</code> rather than <code class="language-plaintext highlighter-rouge">mpz</code> slows down python by another factor of five or so.</p>
<p>The secret oracle we designed is given below.</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">#[macro_use]</span>
<span class="k">extern</span> <span class="n">crate</span> <span class="n">lazy_static</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">collections</span><span class="p">::</span><span class="n">HashMap</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">sync</span><span class="p">::</span><span class="n">Mutex</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">rug</span><span class="p">::{</span><span class="n">Integer</span><span class="p">,</span><span class="n">Complete</span><span class="p">,</span><span class="nn">ops</span><span class="p">::</span><span class="n">Pow</span><span class="p">};</span>
<span class="k">pub</span> <span class="k">static</span> <span class="n">FLAG</span><span class="p">:</span> <span class="o">&</span><span class="p">[</span><span class="nb">u8</span><span class="p">;</span><span class="mi">49</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span><span class="s">"flag{https://www.youtube.com/watch?v=uhTCeZasCmc}"</span><span class="p">;</span>
<span class="k">static</span> <span class="n">P0</span><span class="p">:</span> <span class="nb">i64</span> <span class="o">=</span> <span class="mi">785685301</span><span class="p">;</span>
<span class="k">static</span> <span class="n">P1</span><span class="p">:</span> <span class="nb">i64</span> <span class="o">=</span> <span class="mi">633462701</span><span class="p">;</span>
<span class="k">static</span> <span class="n">GP</span><span class="p">:</span> <span class="nb">i64</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">static</span> <span class="n">Q0</span><span class="p">:</span> <span class="nb">i64</span> <span class="o">=</span> <span class="mi">794309437</span><span class="p">;</span>
<span class="k">static</span> <span class="n">Q1</span><span class="p">:</span> <span class="nb">i64</span> <span class="o">=</span> <span class="mi">942797321</span><span class="p">;</span>
<span class="k">static</span> <span class="n">GQ</span><span class="p">:</span> <span class="nb">i64</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nd">lazy_static!</span><span class="p">(</span>
<span class="k">static</span> <span class="k">ref</span> <span class="n">PPOW</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">P0</span><span class="p">)</span><span class="nf">.pow</span><span class="p">(</span><span class="mi">16u32</span><span class="p">);</span>
<span class="k">static</span> <span class="k">ref</span> <span class="n">QPOW</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">Q0</span><span class="p">)</span><span class="nf">.pow</span><span class="p">(</span><span class="mi">16u32</span><span class="p">);</span>
<span class="k">static</span> <span class="k">ref</span> <span class="n">P</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">(</span><span class="o">&*</span><span class="n">PPOW</span> <span class="o">*</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">P1</span><span class="p">))</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">static</span> <span class="k">ref</span> <span class="n">Q</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">(</span><span class="o">&*</span><span class="n">QPOW</span> <span class="o">*</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">Q1</span><span class="p">))</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">pub</span> <span class="k">static</span> <span class="k">ref</span> <span class="n">N</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">P</span> <span class="o">*</span> <span class="o">&*</span><span class="n">Q</span><span class="p">);</span>
<span class="k">pub</span> <span class="k">static</span> <span class="k">ref</span> <span class="n">ORDER</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">P</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span><span class="nf">.lcm</span><span class="p">(</span><span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">Q</span> <span class="o">-</span> <span class="mi">1</span><span class="p">));</span>
<span class="k">pub</span> <span class="k">static</span> <span class="k">ref</span> <span class="n">G</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="nf">crt</span><span class="p">(</span><span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">GP</span><span class="p">),</span> <span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">GQ</span><span class="p">),</span> <span class="o">&*</span><span class="n">P</span><span class="p">,</span> <span class="o">&*</span><span class="n">Q</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="p">);</span>
<span class="k">fn</span> <span class="nf">crt</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">m1</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">m2</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">)</span> <span class="k">-></span> <span class="nb">Option</span><span class="o"><</span><span class="n">Integer</span><span class="o">></span> <span class="p">{</span>
<span class="k">let</span> <span class="n">common</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">m1</span><span class="nf">.gcd_ref</span><span class="p">(</span><span class="n">m2</span><span class="p">));</span>
<span class="k">let</span> <span class="n">m</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">m1</span><span class="nf">.lcm_ref</span><span class="p">(</span><span class="n">m2</span><span class="p">));</span>
<span class="k">if</span> <span class="n">b</span> <span class="o"><</span> <span class="n">a</span> <span class="p">{</span>
<span class="nf">crt</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">m2</span><span class="p">,</span> <span class="n">m1</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">b</span> <span class="o">-</span> <span class="n">a</span><span class="p">)</span> <span class="o">%</span> <span class="o">&</span><span class="n">common</span> <span class="o">!=</span> <span class="mi">0</span> <span class="p">{</span>
<span class="nb">None</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">q</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">b</span> <span class="o">-</span> <span class="n">a</span><span class="p">)</span> <span class="o">/</span> <span class="o">&</span><span class="n">common</span><span class="p">;</span>
<span class="nf">Some</span><span class="p">((</span><span class="n">a</span> <span class="o">+</span> <span class="n">q</span> <span class="o">*</span> <span class="n">m1</span> <span class="o">*</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">m1</span><span class="o">/&</span><span class="n">common</span><span class="p">)</span><span class="nf">.invert</span><span class="p">(</span><span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">m2</span><span class="o">/&</span><span class="n">common</span><span class="p">))</span><span class="nf">.ok</span><span class="p">()</span><span class="o">?</span><span class="p">)</span> <span class="o">%</span> <span class="n">m</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">type</span> <span class="n">BSKey</span> <span class="o">=</span> <span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">Integer</span><span class="p">);</span>
<span class="k">type</span> <span class="n">BSVal</span> <span class="o">=</span> <span class="n">HashMap</span><span class="o"><</span><span class="n">Integer</span><span class="p">,</span> <span class="n">Integer</span><span class="o">></span><span class="p">;</span>
<span class="k">type</span> <span class="n">BSCache</span> <span class="o">=</span> <span class="n">HashMap</span><span class="o"><</span><span class="n">BSKey</span><span class="p">,</span> <span class="n">BSVal</span><span class="o">></span><span class="p">;</span>
<span class="nd">lazy_static!</span><span class="p">(</span>
<span class="k">static</span> <span class="k">ref</span> <span class="n">BS_CACHE</span><span class="p">:</span> <span class="n">Mutex</span><span class="o"><</span><span class="n">BSCache</span><span class="o">></span> <span class="o">=</span> <span class="nn">Mutex</span><span class="p">::</span><span class="o"><</span><span class="n">BSCache</span><span class="o">></span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="nn">BSCache</span><span class="p">::</span><span class="nf">new</span><span class="p">());</span>
<span class="p">);</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">baby_step</span><span class="p">(</span><span class="n">p</span><span class="p">:</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ell</span><span class="p">:</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">gamma</span><span class="p">:</span> <span class="n">Integer</span><span class="p">)</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">key</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span><span class="nf">.clone</span><span class="p">(),</span> <span class="n">ell</span><span class="nf">.clone</span><span class="p">());</span>
<span class="k">if</span> <span class="o">!</span><span class="n">BS_CACHE</span><span class="nf">.lock</span><span class="p">()</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.contains_key</span><span class="p">(</span><span class="o">&</span><span class="n">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">s</span><span class="p">:</span> <span class="n">Integer</span> <span class="o">=</span> <span class="n">ell</span><span class="nf">.sqrt</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">bs</span> <span class="o">=</span> <span class="nn">BSVal</span><span class="p">::</span><span class="nf">with_capacity</span><span class="p">(</span><span class="n">s</span><span class="nf">.to_usize_wrapping</span><span class="p">());</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">g</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">m</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="k">while</span> <span class="n">m</span> <span class="o"><=</span> <span class="n">s</span> <span class="p">{</span>
<span class="n">bs</span><span class="nf">.insert</span><span class="p">(</span><span class="n">g</span><span class="nf">.clone</span><span class="p">(),</span> <span class="n">m</span><span class="nf">.clone</span><span class="p">());</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">g</span> <span class="o">*</span> <span class="o">&</span><span class="n">gamma</span><span class="p">;</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">g</span> <span class="o">%</span> <span class="o">&</span><span class="n">p</span><span class="p">;</span>
<span class="n">m</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">BS_CACHE</span><span class="nf">.lock</span><span class="p">()</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.insert</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">bs</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">giant_step</span><span class="p">(</span><span class="n">p</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ell</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">g</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">h</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">)</span> <span class="k">-></span> <span class="nb">Option</span><span class="o"><</span><span class="n">Integer</span><span class="o">></span> <span class="p">{</span>
<span class="k">let</span> <span class="n">s</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">ell</span><span class="nf">.sqrt_ref</span><span class="p">())</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">let</span> <span class="n">step</span> <span class="o">=</span> <span class="n">g</span><span class="nf">.clone</span><span class="p">()</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">s</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.invert</span><span class="p">(</span><span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">hh</span> <span class="o">=</span> <span class="n">h</span><span class="nf">.clone</span><span class="p">();</span>
<span class="k">let</span> <span class="n">bs</span> <span class="o">=</span> <span class="o">&</span><span class="n">BS_CACHE</span><span class="nf">.lock</span><span class="p">()</span><span class="nf">.unwrap</span><span class="p">()[</span><span class="o">&</span><span class="p">(</span><span class="n">p</span><span class="nf">.clone</span><span class="p">(),</span> <span class="n">ell</span><span class="nf">.clone</span><span class="p">())];</span>
<span class="k">while</span> <span class="n">m</span> <span class="o"><=</span> <span class="n">s</span> <span class="p">{</span>
<span class="k">if</span> <span class="n">bs</span><span class="nf">.contains_key</span><span class="p">(</span><span class="o">&</span><span class="n">hh</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nf">Some</span><span class="p">((</span><span class="n">bs</span><span class="p">[</span><span class="o">&</span><span class="n">hh</span><span class="p">]</span><span class="nf">.clone</span><span class="p">()</span> <span class="o">+</span> <span class="n">m</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="o">%</span> <span class="n">ell</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">hh</span> <span class="o">=</span> <span class="n">hh</span> <span class="o">*</span> <span class="o">&</span><span class="n">step</span><span class="p">;</span>
<span class="n">hh</span> <span class="o">=</span> <span class="n">hh</span> <span class="o">%</span> <span class="n">p</span><span class="p">;</span>
<span class="n">m</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="nb">None</span>
<span class="p">}</span>
<span class="k">fn</span> <span class="nf">dlog_prime_power</span><span class="p">(</span><span class="n">target</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">p</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">pi</span><span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ei</span><span class="p">:</span> <span class="nb">u32</span><span class="p">)</span> <span class="k">-></span> <span class="nb">Option</span><span class="o"><</span><span class="n">Integer</span><span class="o">></span> <span class="p">{</span>
<span class="k">let</span> <span class="n">ni</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">pi</span><span class="p">)</span><span class="nf">.pow</span><span class="p">(</span><span class="n">ei</span><span class="p">);</span>
<span class="k">let</span> <span class="n">inject</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span><span class="o">/&</span><span class="n">ni</span><span class="p">;</span>
<span class="k">let</span> <span class="n">gi</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&*</span><span class="n">G</span><span class="p">)</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">inject</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="n">hi</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">target</span><span class="p">)</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">inject</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">xi</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">hk_exp</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span><span class="o">/</span><span class="n">pi</span><span class="p">;</span>
<span class="k">let</span> <span class="n">gamma</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&</span><span class="n">gi</span><span class="p">)</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">hk_exp</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="nf">baby_step</span><span class="p">(</span><span class="n">p</span><span class="nf">.clone</span><span class="p">(),</span> <span class="n">pi</span><span class="nf">.clone</span><span class="p">(),</span> <span class="n">gamma</span><span class="nf">.clone</span><span class="p">());</span>
<span class="k">for</span> <span class="n">k</span> <span class="n">in</span> <span class="mi">0</span><span class="o">..</span><span class="n">ei</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">gk</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&</span><span class="n">gi</span><span class="p">)</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">xi</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.invert</span><span class="p">(</span><span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="n">hk</span> <span class="o">=</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&</span><span class="n">gk</span> <span class="o">*</span> <span class="o">&</span><span class="n">hi</span><span class="p">)</span><span class="nf">.pow_mod</span><span class="p">(</span><span class="o">&</span><span class="n">hk_exp</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="n">dk</span> <span class="o">=</span> <span class="nf">giant_step</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">pi</span><span class="p">,</span> <span class="o">&</span><span class="n">gamma</span><span class="p">,</span> <span class="o">&</span><span class="n">hk</span><span class="p">)</span><span class="o">?</span><span class="p">;</span>
<span class="c">// assert_eq!(dk, rho(p, pi, &gamma, &hk));</span>
<span class="n">xi</span> <span class="o">+=</span> <span class="o">&</span><span class="n">dk</span> <span class="o">*</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">pi</span><span class="p">)</span><span class="nf">.pow</span><span class="p">(</span><span class="n">k</span><span class="p">);</span>
<span class="k">if</span> <span class="n">k</span> <span class="o">!=</span> <span class="n">ei</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">{</span> <span class="n">hk_exp</span> <span class="o">=</span> <span class="n">hk_exp</span> <span class="o">/</span> <span class="n">pi</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="nf">Some</span><span class="p">(</span><span class="n">xi</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">dlog</span><span class="p">(</span><span class="n">target</span><span class="p">:</span> <span class="n">Integer</span><span class="p">)</span> <span class="k">-></span> <span class="nb">Option</span><span class="o"><</span><span class="n">Integer</span><span class="o">></span> <span class="p">{</span>
<span class="k">let</span> <span class="n">modp</span> <span class="o">=</span> <span class="nf">crt</span><span class="p">(</span>
<span class="o">&</span><span class="nf">crt</span><span class="p">(</span>
<span class="o">&</span><span class="nf">dlog_prime_power</span><span class="p">(</span><span class="o">&</span><span class="n">target</span><span class="p">,</span> <span class="o">&*</span><span class="n">P</span><span class="p">,</span> <span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="mi">1</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nf">dlog_prime_power</span><span class="p">(</span><span class="o">&</span><span class="n">target</span><span class="p">,</span> <span class="o">&*</span><span class="n">P</span><span class="p">,</span> <span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">P0</span><span class="p">),</span> <span class="mi">16</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span>
<span class="o">&*</span><span class="n">PPOW</span>
<span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nf">dlog_prime_power</span><span class="p">(</span><span class="o">&</span><span class="n">target</span><span class="p">,</span> <span class="o">&*</span><span class="n">P</span><span class="p">,</span> <span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">P1</span><span class="p">),</span> <span class="mi">1</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="o">&*</span><span class="n">PPOW</span><span class="p">),</span>
<span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">P1</span><span class="p">)</span>
<span class="p">)</span><span class="o">?</span><span class="p">;</span>
<span class="k">let</span> <span class="n">modq</span> <span class="o">=</span> <span class="nf">crt</span><span class="p">(</span>
<span class="o">&</span><span class="nf">crt</span><span class="p">(</span>
<span class="o">&</span><span class="nf">dlog_prime_power</span><span class="p">(</span><span class="o">&</span><span class="n">target</span><span class="p">,</span> <span class="o">&*</span><span class="n">Q</span><span class="p">,</span> <span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="mi">1</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nf">dlog_prime_power</span><span class="p">(</span><span class="o">&</span><span class="n">target</span><span class="p">,</span> <span class="o">&*</span><span class="n">Q</span><span class="p">,</span> <span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">Q0</span><span class="p">),</span> <span class="mi">16</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span>
<span class="o">&*</span><span class="n">QPOW</span>
<span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nf">dlog_prime_power</span><span class="p">(</span><span class="o">&</span><span class="n">target</span><span class="p">,</span> <span class="o">&*</span><span class="n">Q</span><span class="p">,</span> <span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">Q1</span><span class="p">),</span> <span class="mi">1</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
<span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="o">&*</span><span class="n">QPOW</span><span class="p">),</span>
<span class="o">&</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="n">Q1</span><span class="p">)</span>
<span class="p">)</span><span class="o">?</span><span class="p">;</span>
<span class="nf">Some</span><span class="p">(</span><span class="nf">crt</span><span class="p">(</span><span class="o">&</span><span class="n">modp</span><span class="p">,</span> <span class="o">&</span><span class="n">modq</span><span class="p">,</span> <span class="o">&</span><span class="p">(</span><span class="o">&*</span><span class="n">P</span> <span class="o">-</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">1</span><span class="p">)),</span> <span class="o">&</span><span class="p">(</span><span class="o">&*</span><span class="n">Q</span> <span class="o">-</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">1</span><span class="p">)))</span><span class="o">?</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Originally, we were planning to use Pollard’s Rho algorithm instead of BSGS:</p>
<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="nf">f</span><span class="p">(</span><span class="n">tup</span> <span class="p">:</span> <span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">Integer</span><span class="p">),</span> <span class="n">g</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">target</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">p</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ell</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">)</span> <span class="k">-></span> <span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">Integer</span><span class="p">)</span> <span class="p">{</span>
<span class="k">let</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="o">=</span> <span class="n">tup</span><span class="p">;</span>
<span class="k">match</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="o">&</span><span class="n">x</span> <span class="o">%</span> <span class="mi">3</span><span class="p">)</span><span class="nf">.to_i64</span><span class="p">()</span><span class="nf">.unwrap</span><span class="p">()</span> <span class="p">{</span>
<span class="mi">0</span> <span class="k">=></span> <span class="p">{</span>
<span class="p">((</span><span class="o">&</span><span class="n">x</span> <span class="o">*</span> <span class="o">&</span><span class="n">x</span><span class="p">)</span><span class="nf">.complete</span><span class="p">()</span> <span class="o">%</span> <span class="n">p</span><span class="p">,</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">a</span><span class="p">)</span> <span class="o">%</span> <span class="n">ell</span><span class="p">,</span> <span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">b</span><span class="p">)</span> <span class="o">%</span> <span class="n">ell</span><span class="p">)</span>
<span class="p">},</span>
<span class="mi">1</span> <span class="k">=></span> <span class="p">{</span>
<span class="p">((</span><span class="n">target</span> <span class="o">*</span> <span class="n">x</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="p">(</span><span class="n">b</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
<span class="p">},</span>
<span class="mi">2</span> <span class="k">=></span> <span class="p">{</span>
<span class="p">((</span><span class="n">g</span> <span class="o">*</span> <span class="n">x</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">,</span> <span class="p">(</span><span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="n">b</span><span class="p">)</span>
<span class="p">},</span>
<span class="mi">_</span> <span class="k">=></span> <span class="p">{</span><span class="nd">unreachable!</span><span class="p">();}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">rho</span><span class="p">(</span><span class="n">p</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ell</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">g</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">,</span> <span class="n">target</span> <span class="p">:</span> <span class="o">&</span><span class="n">Integer</span><span class="p">)</span> <span class="k">-></span> <span class="n">Integer</span> <span class="p">{</span>
<span class="k">if</span> <span class="n">g</span> <span class="o">==</span> <span class="n">target</span> <span class="p">{</span> <span class="k">return</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="p">}</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="nn">Integer</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
<span class="k">loop</span> <span class="p">{</span>
<span class="n">a</span> <span class="o">=</span> <span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">ell</span><span class="p">);</span>
<span class="n">b</span> <span class="o">=</span> <span class="nf">f</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">ell</span><span class="p">);</span>
<span class="n">b</span> <span class="o">=</span> <span class="nf">f</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">ell</span><span class="p">);</span>
<span class="k">if</span> <span class="n">a</span><span class="na">.0</span> <span class="o">==</span> <span class="n">b</span><span class="na">.0</span> <span class="p">{</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">((</span><span class="n">a</span><span class="na">.1</span> <span class="o">-</span> <span class="n">b</span><span class="na">.1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">b</span><span class="na">.2</span> <span class="o">-</span> <span class="n">a</span><span class="na">.2</span><span class="p">)</span><span class="nf">.invert</span><span class="p">(</span><span class="n">ell</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span> <span class="o">%</span> <span class="n">ell</span> <span class="o">+</span> <span class="n">ell</span><span class="p">)</span> <span class="o">%</span> <span class="n">ell</span>
<span class="p">}</span>
</code></pre></div></div>
<p>but we found BSGS didnt use too much memory and the additional speed up by saving the baby steps for the repeated prime factors of $p$ and $q$ meant ultimately BSGS was a better pick for this challenge.</p>
<p>For those interested, a python implementation of essentially what is given above is included for comparison:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">ceil</span><span class="p">,</span> <span class="n">sqrt</span><span class="p">,</span> <span class="n">gcd</span><span class="p">,</span> <span class="n">lcm</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">gmpy2</span> <span class="kn">import</span> <span class="n">mpz</span>
<span class="k">def</span> <span class="nf">bsgs</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">upper_bound</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">upper_bound</span><span class="p">:</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">ceil</span><span class="p">(</span><span class="n">sqrt</span><span class="p">(</span><span class="n">upper_bound</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">ceil</span><span class="p">(</span><span class="n">sqrt</span><span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">bsgs</span><span class="p">,</span> <span class="s">'baby_steps'</span><span class="p">):</span>
<span class="n">bsgs</span><span class="p">.</span><span class="n">baby_steps</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="n">gi</span> <span class="o">=</span> <span class="n">mpz</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
<span class="n">bsgs</span><span class="p">.</span><span class="n">baby_steps</span><span class="p">[</span><span class="n">gi</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span>
<span class="n">gi</span> <span class="o">=</span> <span class="p">(</span><span class="n">gi</span> <span class="o">*</span> <span class="n">g</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">m</span> <span class="o">*</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
<span class="n">hi</span> <span class="o">=</span> <span class="n">h</span>
<span class="c1"># giant steps
</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
<span class="k">if</span> <span class="n">hi</span> <span class="ow">in</span> <span class="n">bsgs</span><span class="p">.</span><span class="n">baby_steps</span><span class="p">:</span>
<span class="k">return</span> <span class="n">j</span> <span class="o">*</span> <span class="n">m</span> <span class="o">+</span> <span class="n">bsgs</span><span class="p">.</span><span class="n">baby_steps</span><span class="p">[</span><span class="n">hi</span><span class="p">]</span>
<span class="n">hi</span> <span class="o">=</span> <span class="p">(</span><span class="n">hi</span> <span class="o">*</span> <span class="n">c</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="c1"># No solution
</span> <span class="k">return</span> <span class="bp">None</span>
<span class="k">def</span> <span class="nf">crt</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">ns_fac</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">ns</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span><span class="o">**</span><span class="n">e</span> <span class="k">for</span> <span class="n">p</span><span class="p">,</span><span class="n">e</span> <span class="ow">in</span> <span class="n">ns_fac</span><span class="p">]</span>
<span class="n">common</span> <span class="o">=</span> <span class="n">gcd</span><span class="p">(</span><span class="o">*</span><span class="n">ns</span><span class="p">)</span>
<span class="n">ns</span> <span class="o">=</span> <span class="p">[</span><span class="n">n</span> <span class="o">//</span> <span class="n">common</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">ns</span><span class="p">]</span>
<span class="k">for</span> <span class="n">xi</span><span class="p">,</span> <span class="n">ni</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">ns</span><span class="p">):</span>
<span class="n">yi</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="n">ni</span>
<span class="n">zi</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">yi</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">ni</span><span class="p">)</span>
<span class="n">x</span> <span class="o">+=</span> <span class="n">xi</span> <span class="o">*</span> <span class="n">yi</span> <span class="o">*</span> <span class="n">zi</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">%</span> <span class="n">n</span>
<span class="k">def</span> <span class="nf">pohlig_hellman</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">h</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="n">n_factors</span><span class="p">):</span>
<span class="n">dlogs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">pi</span><span class="p">,</span> <span class="n">ei</span> <span class="ow">in</span> <span class="n">n_factors</span><span class="p">:</span>
<span class="c1"># Set up for each step
</span> <span class="n">ni</span> <span class="o">=</span> <span class="n">pi</span><span class="o">**</span><span class="n">ei</span>
<span class="n">gi</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">n</span> <span class="o">//</span> <span class="n">ni</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">hi</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">n</span> <span class="o">//</span> <span class="n">ni</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="c1"># Groups of prime-power order
</span> <span class="n">xi</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">hk_exp</span> <span class="o">=</span> <span class="n">ni</span> <span class="o">//</span> <span class="n">pi</span>
<span class="n">gamma</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">gi</span><span class="p">,</span> <span class="n">hk_exp</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">ei</span><span class="p">):</span>
<span class="c1"># Create hk in <γ>
</span> <span class="n">gk</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">gi</span><span class="p">,</span> <span class="o">-</span><span class="n">xi</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">hk</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">gk</span><span class="o">*</span><span class="n">hi</span><span class="p">,</span> <span class="n">hk_exp</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="c1"># make call to rust
</span> <span class="n">dk</span> <span class="o">=</span> <span class="n">bsgs</span><span class="p">(</span><span class="n">gamma</span><span class="p">,</span> <span class="n">hk</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">upper_bound</span><span class="o">=</span><span class="n">pi</span><span class="p">)</span>
<span class="c1"># increment the secret
</span> <span class="n">xi</span> <span class="o">+=</span> <span class="n">dk</span><span class="o">*</span><span class="p">(</span><span class="n">pi</span><span class="o">**</span><span class="n">k</span><span class="p">)</span>
<span class="c1"># Reduce the exponent
</span> <span class="n">hk_exp</span> <span class="o">=</span> <span class="n">hk_exp</span> <span class="o">//</span> <span class="n">pi</span>
<span class="k">del</span> <span class="n">bsgs</span><span class="p">.</span><span class="n">baby_steps</span>
<span class="n">dlogs</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">xi</span><span class="p">)</span>
<span class="k">return</span> <span class="n">crt</span><span class="p">(</span><span class="n">dlogs</span><span class="p">,</span> <span class="n">n_factors</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">dlog_backdoor</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">h</span><span class="p">,</span><span class="n">N</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="n">q</span><span class="p">):</span>
<span class="n">np_factors</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">785685301</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span> <span class="p">(</span><span class="mi">633462701</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
<span class="n">np</span> <span class="o">=</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span>
<span class="n">nq_factors</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">794309437</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span> <span class="p">(</span><span class="mi">942797321</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
<span class="n">nq</span> <span class="o">=</span> <span class="n">q</span><span class="o">-</span><span class="mi">1</span>
<span class="n">xp</span> <span class="o">=</span> <span class="n">pohlig_hellman</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">h</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="n">np</span><span class="p">,</span><span class="n">np_factors</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">xp</span><span class="p">,</span><span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="nb">pow</span><span class="p">(</span><span class="n">h</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">p</span><span class="p">)</span>
<span class="n">xq</span> <span class="o">=</span> <span class="n">pohlig_hellman</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">h</span><span class="p">,</span><span class="n">q</span><span class="p">,</span><span class="n">nq</span><span class="p">,</span><span class="n">nq_factors</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">xq</span><span class="p">,</span><span class="n">q</span><span class="p">)</span> <span class="o">==</span> <span class="nb">pow</span><span class="p">(</span><span class="n">h</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="n">q</span><span class="p">)</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">crt</span><span class="p">([</span><span class="n">xp</span><span class="p">,</span> <span class="n">xq</span><span class="p">],</span> <span class="p">[(</span><span class="n">np</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="n">nq</span><span class="p">,</span> <span class="mi">1</span><span class="p">)],</span> <span class="n">np</span><span class="o">*</span><span class="n">nq</span><span class="p">)</span>
<span class="k">return</span> <span class="n">x</span> <span class="o">%</span> <span class="n">order</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">mpz</span><span class="p">(</span><span class="mi">26713395582018967511973684657814004241261156269415358729692119332394978760010789226380713422950849602617267772456438810738143011486768190080495256375003</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">mpz</span><span class="p">(</span><span class="mi">47346065295850807479811692397225726348630781686943994678601678975909956314423885777086052944991365707991632035242429229693774362516043822438274496319123</span><span class="p">)</span>
<span class="n">np</span> <span class="o">=</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span>
<span class="n">nq</span> <span class="o">=</span> <span class="n">q</span><span class="o">-</span><span class="mi">1</span>
<span class="n">N</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">q</span>
<span class="n">order</span> <span class="o">=</span> <span class="n">lcm</span><span class="p">(</span><span class="n">np</span><span class="p">,</span><span class="n">nq</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">mpz</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">mpz</span><span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="n">order</span><span class="p">))</span>
<span class="n">h</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">x</span><span class="p">,</span><span class="n">N</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'x = </span><span class="si">{</span><span class="n">x</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
<span class="n">x_guess</span> <span class="o">=</span> <span class="n">dlog_backdoor</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">h</span><span class="p">,</span><span class="n">N</span><span class="p">,</span><span class="n">p</span><span class="p">,</span><span class="n">q</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'x_guess = </span><span class="si">{</span><span class="n">x_guess</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Time taken: </span><span class="si">{</span><span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">t</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Solution found: </span><span class="si">{</span><span class="n">x</span> <span class="o">==</span> <span class="n">x_guess</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Solution found: </span><span class="si">{</span><span class="nb">pow</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="n">x_guess</span><span class="p">,</span><span class="n">N</span><span class="p">)</span> <span class="o">==</span> <span class="n">h</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<p>One alternative we briefly explored was using even larger prime factors and performing a precomputation step with GNFS (as implemented by cado-nfs) to allow fast on-the-spot computation of the discrete logarithms. While testing, this had a few drawbacks. First off, the precomputation time doesn’t depend on the subgroup size, but on the size of the modulus, which would allow us to alleviate the smooth $p - 1$ weakness, but at the cost of a very heavy precomputation if we wanted to keep $n$ hard enough to factor. Secondly, even for smaller primes $p$, we found that the overhead of calling into cado to perform the online discrete logarithm had a large overhead.</p>
<p>Overall, we are happy with our chosen backdoor and feel that it was the best solution in the inherent trade-off between the speed of the oracle — since we don’t want a solution to take hours to perform either — the precomputation cost before the CTF and the room for unintended factorization of $n$. We are unaware of any team having succeeded in factoring $n$ without recovering the group order, so it does appear that our approach was successful enough to withstand what some smart CTF players tried to do to it.</p>["Robin & Jack"]CryptoHack was asked to make some challenges for CSAW 2021 and Bits was our submission for the qualifiers, written by Robin and Jack. For those who qualified for the finals, you’ll have the chance to solve a few more CryptoHack challenges, but for now, we wanted to go through Bits, explain some potential solutions and some cover a few interesting things we learnt when building the challenge itself.CryptoCTF 2021 - Easy2021-08-06T00:00:00+00:002021-08-06T00:00:00+00:00https://blog.cryptohack.org/cryptoctf-easy<p>Last week, CryptoHackers got together to play CryptoCTF for the second time as a team. We solved 26/29 of the challenges during the 24 hour window and came third overall. First and second places went to Super Guessers (Rkm and Rbtree are very friendly faces from CryptoHack) and a Vietnamese team working together to support the spirit of Ho Chi Minh city and nearby provinces. Congratulations to them both.</p>
<p><img src="/assets/images/cryptoctf-2021.png" alt="CTF Scoreboard" /></p>
<p>Not only was it a lot of fun for us all to play together, but it was amazing to see how many CryptoHack friends played the CTF either solo or in small teams and who were able to get a top 15 spot. We’re honoured to have so many talented people in our Discord, chatting with us about maths and cryptography. We even have guest writeups from <a href="https://rkm0959.tistory.com">rkm0959</a> talking about the solutions of <a href="https://blog.cryptohack.org/cryptoctf2021-hard#dorsa">DoRSA</a> and <a href="https://blog.cryptohack.org/cryptoctf2021-hard#polish">Polish</a>.</p>
<p>Here are the write-ups for the easiest challenges in the CTF. You can find write ups for the <a href="https://blog.cryptohack.org/cryptoctf2021-medium">medium</a> and <a href="https://blog.cryptohack.org/cryptoctf2021-hard">hard</a> challenges as other posts on our blog.</p>
<p>Thank you to everyone who played for the CryptoHackers, and to ASIS CTF for organising this enjoyable event. Congratulations again to Super Guessers for being the ultimate crypto heros!</p>
<p><em>We will be publishing more writeups here as soon as they are finished. If you spot a mistake or an improvement that could be made, please ping jack or hyperreality on CryptoHack Discord.</em></p>
<h2 id="challenges">Challenges</h2>
<table>
<thead>
<tr>
<th>Challenge Name</th>
<th>Category</th>
<th>Solved By</th>
<th style="text-align: right">Points</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#farm">Farm</a></td>
<td>Finite Fields</td>
<td>evilmuffinha</td>
<td style="text-align: right">41</td>
</tr>
<tr>
<td><a href="#keybase">Keybase</a></td>
<td>AES</td>
<td>UnblvR (Coming Soon)</td>
<td style="text-align: right">48</td>
</tr>
<tr>
<td><a href="#rima">Rima</a></td>
<td>Encoding</td>
<td>Willwam845, randomdude999</td>
<td style="text-align: right">56</td>
</tr>
<tr>
<td><a href="#symbols">Symbols</a></td>
<td>Misc</td>
<td>Q7</td>
<td style="text-align: right">70</td>
</tr>
<tr>
<td><a href="#hyper-normal">Hyper Normal</a></td>
<td>Misc</td>
<td>Q7</td>
<td style="text-align: right">71</td>
</tr>
<tr>
<td><a href="#salt-and-pepper">Salt and Pepper</a></td>
<td>Hash length extension</td>
<td>Willwam845</td>
<td style="text-align: right">71</td>
</tr>
<tr>
<td><a href="#titu">Titu</a></td>
<td>Diophantine equations</td>
<td>Jack</td>
<td style="text-align: right">69</td>
</tr>
<tr>
<td><a href="#hamul">Hamul</a></td>
<td>RSA</td>
<td>Lyutoon</td>
<td style="text-align: right">83</td>
</tr>
</tbody>
</table>
<h2 id="farm">Farm</h2>
<h3 id="challenge">Challenge</h3>
<blockquote>
<p>Explore the Farm very carefully!</p>
<ul>
<li><a href="https://cryp.toc.tf/tasks/farm_0a16ef99ff1f979039cda1a685ac0344b927eee6.txz">farm.txz</a></li>
</ul>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env sage
</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">string</span><span class="p">,</span> <span class="n">base64</span><span class="p">,</span> <span class="n">math</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="n">ALPHABET</span> <span class="o">=</span> <span class="n">string</span><span class="p">.</span><span class="n">printable</span><span class="p">[:</span><span class="mi">62</span><span class="p">]</span> <span class="o">+</span> <span class="s">'</span><span class="se">\\</span><span class="s">='</span>
<span class="n">F</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="mi">64</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">key</span> <span class="o">=</span> <span class="p">[</span><span class="n">F</span><span class="p">[</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">63</span><span class="p">)]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">)]</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">math</span><span class="p">.</span><span class="n">prod</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="c1"># Optimization the key length :D
</span> <span class="k">return</span> <span class="n">key</span>
<span class="k">def</span> <span class="nf">maptofarm</span><span class="p">(</span><span class="n">c</span><span class="p">):</span>
<span class="k">assert</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">ALPHABET</span>
<span class="k">return</span> <span class="n">F</span><span class="p">[</span><span class="n">ALPHABET</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="n">c</span><span class="p">)]</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="n">m64</span> <span class="o">=</span> <span class="n">base64</span><span class="p">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="n">enc</span><span class="p">,</span> <span class="n">pkey</span> <span class="o">=</span> <span class="s">''</span><span class="p">,</span> <span class="n">key</span><span class="o">**</span><span class="mi">5</span> <span class="o">+</span> <span class="n">key</span><span class="o">**</span><span class="mi">3</span> <span class="o">+</span> <span class="n">key</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">m64</span><span class="p">:</span>
<span class="n">enc</span> <span class="o">+=</span> <span class="n">ALPHABET</span><span class="p">[</span><span class="n">F</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="n">pkey</span> <span class="o">*</span> <span class="n">maptofarm</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">m</span><span class="p">)))]</span>
<span class="k">return</span> <span class="n">enc</span>
<span class="c1"># KEEP IT SECRET
</span><span class="n">key</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">(</span><span class="mi">14</span><span class="p">)</span> <span class="c1"># I think 64**14 > 2**64 is not brute-forcible :P
</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'enc = </span><span class="si">{</span><span class="n">enc</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<p>The key is the product of 14 random elements selected from $GF(64)$.</p>
<h3 id="solution">Solution</h3>
<p>Note that the product of two elements of $GF(64)$ is still an element of $GF(64)$. Inductively, the key lies in $GF(64)$. That is, the key space is just 64 and hence we are able to brute-force the key.</p>
<h3 id="implementation">Implementation</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env sage
</span><span class="kn">import</span> <span class="nn">string</span>
<span class="kn">import</span> <span class="nn">base64</span>
<span class="n">enc</span> <span class="o">=</span> <span class="s">"805c9GMYuD5RefTmabUNfS9N9YrkwbAbdZE0df91uCEytcoy9FDSbZ8Ay8jj"</span>
<span class="n">ALPHABET</span> <span class="o">=</span> <span class="n">string</span><span class="p">.</span><span class="n">printable</span><span class="p">[:</span><span class="mi">62</span><span class="p">]</span> <span class="o">+</span> <span class="s">'</span><span class="se">\\</span><span class="s">='</span>
<span class="n">F</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="mi">64</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">farmtomap</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="k">assert</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">F</span>
<span class="k">return</span> <span class="n">ALPHABET</span><span class="p">[</span><span class="n">F</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="n">f</span><span class="p">)]</span>
<span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="n">dec</span><span class="p">,</span> <span class="n">pkey</span> <span class="o">=</span> <span class="s">''</span><span class="p">,</span> <span class="n">key</span><span class="o">**</span><span class="mi">5</span> <span class="o">+</span> <span class="n">key</span><span class="o">**</span><span class="mi">3</span> <span class="o">+</span> <span class="n">key</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">msg</span><span class="p">:</span>
<span class="n">dec</span> <span class="o">+=</span> <span class="n">farmtomap</span><span class="p">(</span><span class="n">F</span><span class="p">[</span><span class="n">ALPHABET</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="n">m</span><span class="p">)]</span> <span class="o">/</span> <span class="n">pkey</span><span class="p">)</span>
<span class="k">return</span> <span class="n">base64</span><span class="p">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">dec</span><span class="p">)</span>
<span class="k">for</span> <span class="n">possible_key</span> <span class="ow">in</span> <span class="n">F</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">plaintext</span> <span class="o">=</span> <span class="n">decrypt</span><span class="p">(</span><span class="n">enc</span><span class="p">,</span> <span class="n">possible_key</span><span class="p">)</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">"CCTF{"</span> <span class="ow">in</span> <span class="n">plaintext</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">plaintext</span><span class="p">.</span><span class="n">decode</span><span class="p">())</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">continue</span>
</code></pre></div></div>
<h5 id="flag">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{EnCrYp7I0n_4nD_5u8STitUtIn9_iN_Fi3Ld!}</code></p>
<h2 id="keybase">Keybase</h2>
<h3 id="challenge-1">Challenge</h3>
<blockquote>
<p>Recovering secrets is hard, but there is always some easy parts!
<code class="language-plaintext highlighter-rouge">nc 01.cr.yp.toc.tf 17010</code></p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util</span> <span class="kn">import</span> <span class="n">number</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">import</span> <span class="nn">os</span><span class="p">,</span> <span class="n">sys</span><span class="p">,</span> <span class="n">random</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">():</span>
<span class="n">iv</span><span class="p">,</span> <span class="n">key</span> <span class="o">=</span> <span class="p">[</span><span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="s">'01'</span><span class="p">]</span>
<span class="k">return</span> <span class="n">iv</span><span class="p">,</span> <span class="n">key</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">iv</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="n">aes</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">iv</span><span class="p">)</span>
<span class="k">return</span> <span class="n">aes</span><span class="p">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">enc</span><span class="p">,</span> <span class="n">iv</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="n">aes</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">iv</span><span class="p">)</span>
<span class="k">return</span> <span class="n">aes</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">enc</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" hi all, welcome to the simple KEYBASE cryptography task, try to "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" decrypt the encrypted message and get the flag as a nice prize! "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">iv</span><span class="p">,</span> <span class="n">key</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">()</span>
<span class="n">flag_enc</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">iv</span><span class="p">,</span> <span class="n">key</span><span class="p">).</span><span class="nb">hex</span><span class="p">()</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[G]et the encrypted flag </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[T]est the encryption </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'g'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| encrypt(flag) ="</span><span class="p">,</span> <span class="n">flag_enc</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'t'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Please send your 32 bytes message to encrypt: "</span><span class="p">)</span>
<span class="n">msg_inp</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">msg_inp</span><span class="p">)</span> <span class="o">==</span> <span class="mi">32</span><span class="p">:</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">msg_inp</span><span class="p">,</span> <span class="n">iv</span><span class="p">,</span> <span class="n">key</span><span class="p">).</span><span class="nb">hex</span><span class="p">()</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="mi">4</span> <span class="o">-</span> <span class="n">r</span>
<span class="n">mask_key</span> <span class="o">=</span> <span class="n">key</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">].</span><span class="nb">hex</span><span class="p">()</span> <span class="o">+</span> <span class="s">'*'</span> <span class="o">*</span> <span class="mi">4</span>
<span class="n">mask_enc</span> <span class="o">=</span> <span class="n">enc</span><span class="p">[:</span><span class="n">r</span><span class="p">]</span> <span class="o">+</span> <span class="s">'*'</span> <span class="o">*</span> <span class="mi">28</span> <span class="o">+</span> <span class="n">enc</span><span class="p">[</span><span class="mi">32</span><span class="o">-</span><span class="n">s</span><span class="p">:]</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| enc ="</span><span class="p">,</span> <span class="n">mask_enc</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| key ="</span><span class="p">,</span> <span class="n">mask_key</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| SEND 32 BYTES MESSAGE :X"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<h3 id="solution-1">Solution</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="k">def</span> <span class="nf">bxor</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span><span class="n">s2</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">b</span><span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">bytes</span><span class="p">([</span><span class="n">a</span> <span class="o">^</span> <span class="n">b</span><span class="p">])</span> <span class="k">for</span> <span class="n">a</span><span class="p">,</span><span class="n">b</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span><span class="n">s2</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"01.cr.yp.toc.tf"</span><span class="p">,</span> <span class="mi">17010</span><span class="p">)</span>
<span class="c1"># [G]et the encrypted flag
</span><span class="n">r</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"[Q]uit</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="s">"G"</span><span class="p">)</span>
<span class="n">enc_flag</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">().</span><span class="n">decode</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
<span class="c1"># [T]est the encryption
# Loop this a few times until we get 4 characters of the plaintext in the beginning
# as this makes the brute-force a bit easier code-wise
</span><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"[Q]uit</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="s">"T"</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"Please send your 32 bytes message to encrypt: </span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mi">32</span><span class="p">)</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">().</span><span class="n">decode</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">().</span><span class="n">decode</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="s">" = "</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">prefix</span> <span class="o">=</span> <span class="n">enc</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"*"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">prefix</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
<span class="n">prefix</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">prefix</span><span class="p">)</span>
<span class="k">break</span>
<span class="c1"># Brute force the last 2 bytes of the key
</span><span class="n">key</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">key</span><span class="p">[:</span><span class="o">-</span><span class="mi">4</span><span class="p">])</span> <span class="o">+</span> <span class="sa">b</span><span class="s">"</span><span class="se">\x00\x00</span><span class="s">"</span>
<span class="k">for</span> <span class="n">k1</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">):</span>
<span class="n">key</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">k1</span>
<span class="k">for</span> <span class="n">k2</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">):</span>
<span class="n">key</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">k2</span>
<span class="c1"># Decrypt the second block alone, without CBC/IV, and XOR with the two unmasked bytes.
</span> <span class="c1"># Result should be original plaintext "AA.....".
</span> <span class="k">if</span> <span class="n">bxor</span><span class="p">(</span><span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">).</span><span class="n">decrypt</span><span class="p">(</span><span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">enc</span><span class="p">[</span><span class="o">-</span><span class="mi">32</span><span class="p">:])),</span> <span class="sa">b</span><span class="s">"AA"</span><span class="p">)</span> <span class="o">==</span> <span class="n">prefix</span><span class="p">:</span>
<span class="c1"># Recover full first block by xoring second block with known plaintext
</span> <span class="n">block</span> <span class="o">=</span> <span class="n">bxor</span><span class="p">(</span><span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">).</span><span class="n">decrypt</span><span class="p">(</span><span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">enc</span><span class="p">[</span><span class="o">-</span><span class="mi">32</span><span class="p">:])),</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mi">16</span><span class="p">)</span>
<span class="c1"># IV is whatever the first block was XORed with prior to encryption. Decrypt and XOR.
</span> <span class="n">IV</span> <span class="o">=</span> <span class="n">bxor</span><span class="p">(</span><span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">).</span><span class="n">decrypt</span><span class="p">(</span><span class="n">block</span><span class="p">),</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mi">16</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Recovered key candidate: </span><span class="si">{</span><span class="n">key</span><span class="p">.</span><span class="nb">hex</span><span class="p">()</span><span class="si">}</span><span class="s"> with IV </span><span class="si">{</span><span class="n">IV</span><span class="p">.</span><span class="nb">hex</span><span class="p">()</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">IV</span><span class="p">).</span><span class="n">decrypt</span><span class="p">(</span><span class="n">enc_flag</span><span class="p">))</span>
</code></pre></div></div>
<h5 id="flag-1">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{h0W_R3cOVER_7He_5eCrET_1V?}</code></p>
<h2 id="rima">Rima</h2>
<h3 id="challenge-2">Challenge</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">FLAG</span>
<span class="k">def</span> <span class="nf">nextPrime</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">n</span> <span class="o">+=</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">return</span> <span class="n">n</span>
<span class="n">f</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">bin</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">FLAG</span><span class="p">.</span><span class="nb">hex</span><span class="p">(),</span> <span class="mi">16</span><span class="p">))[</span><span class="mi">2</span><span class="p">:]]</span>
<span class="n">f</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">))</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">g</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="p">[[</span><span class="n">_</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">f</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">]]</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="o">>></span> <span class="mi">2</span><span class="p">)</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="p">[</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">]:</span>
<span class="k">for</span> <span class="n">__</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">c</span><span class="p">):</span> <span class="n">_</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="o">-</span> <span class="n">c</span><span class="p">):</span> <span class="n">_</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">_</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="n">c</span><span class="p">]</span>
<span class="n">g</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">__</span><span class="p">]),</span> <span class="mi">5</span><span class="p">)</span> <span class="k">for</span> <span class="n">__</span> <span class="ow">in</span> <span class="p">[</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">]]</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="p">[</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">_</span> <span class="o">==</span> <span class="n">g</span><span class="p">:</span>
<span class="n">fname</span> <span class="o">=</span> <span class="s">'g'</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">fname</span> <span class="o">=</span> <span class="s">'h'</span>
<span class="n">of</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">fname</span><span class="si">}</span><span class="s">.enc'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span>
<span class="n">of</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">_</span><span class="p">))</span>
<span class="n">of</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p>The flag is encoded using a bunch of weird looking operations, and then we get the two files <code class="language-plaintext highlighter-rouge">g.enc</code> and <code class="language-plaintext highlighter-rouge">h.enc</code></p>
<h3 id="solution-2">Solution</h3>
<p>Firstly, we can deduce the flag length as 32 bytes by simply testing some letter repeated some number of times as the flag, then checking the length of the output and comparing it to the size of <code class="language-plaintext highlighter-rouge">g.enc</code>.</p>
<p>We will work through the steps in reverse order.</p>
<h4 id="step-1">Step 1</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">g</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">__</span><span class="p">]),</span> <span class="mi">5</span><span class="p">)</span> <span class="k">for</span> <span class="n">__</span> <span class="ow">in</span> <span class="p">[</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">]]</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="p">[</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">]:</span>
<span class="k">if</span> <span class="n">_</span> <span class="o">==</span> <span class="n">g</span><span class="p">:</span>
<span class="n">fname</span> <span class="o">=</span> <span class="s">'g'</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">fname</span> <span class="o">=</span> <span class="s">'h'</span>
<span class="n">of</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">fname</span><span class="si">}</span><span class="s">.enc'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span>
<span class="n">of</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">_</span><span class="p">))</span>
<span class="n">of</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p>Firstly, each file contains bytes, which we need to convert to a base 10 integer. Then, we need to convert this base 10 integer into a base 5 integer. We can do this quite easily with <code class="language-plaintext highlighter-rouge">gmpy2</code>’s <code class="language-plaintext highlighter-rouge">digits</code> function.</p>
<h4 id="step-2">Step 2</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">c</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="o">>></span> <span class="mi">2</span><span class="p">)</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="p">[</span><span class="n">g</span><span class="p">,</span> <span class="n">h</span><span class="p">]:</span>
<span class="k">for</span> <span class="n">__</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">c</span><span class="p">):</span> <span class="n">_</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="o">-</span> <span class="n">c</span><span class="p">):</span> <span class="n">_</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">_</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="n">c</span><span class="p">]</span>
</code></pre></div></div>
<p>These next steps add some elements of the list to other elements of the list. We can work out the value of <code class="language-plaintext highlighter-rouge">len(_) - c</code> by just running the program with a random 32 byte flag, and then to reverse it, we just need to ensure that we change the addition to subtraction, and work in reverse order, as the later elements of the list are not affected by the earlier ones (but not vice versa).</p>
<p>We also then need to trim $c$ amound of 0’s from the start of the list at the end. $c$ can again be worked out by just running the program.</p>
<h4 id="step-3">Step 3</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">))</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">g</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="p">[[</span><span class="n">_</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">f</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">]]</span>
</code></pre></div></div>
<p>This step simply takes the list $f$ and duplicates it $a$ and $b$ times, storing them in $g$ and $h$. We can either manually find the repeating sequence, work out the values of $a$ and $b$ and simply split $g$ into $a$ chunks (or $h$ into $b$ chunks), or we can simply know the length of $f$, and take the first $len(f)$ elements of $g$ to get the original $f$.</p>
<h4 id="step-4">Step 4</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">f</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">bin</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">FLAG</span><span class="p">.</span><span class="nb">hex</span><span class="p">(),</span> <span class="mi">16</span><span class="p">))[</span><span class="mi">2</span><span class="p">:]]</span>
<span class="n">f</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
</code></pre></div></div>
<p>Our last step is again quite similar to step 2, we work out the length of $f$ by running the program, and then going in reverse order, changing the addition to a subtraction instead. We can then obtain the flag by converting the list into a string, which should be the binary string of the flag.</p>
<h3 id="implementation-1">Implementation</h3>
<p>Putting this all together, this looks like this:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">gmpy2</span> <span class="kn">import</span> <span class="n">digits</span>
<span class="c1"># Step 1
</span><span class="n">g</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">digits</span><span class="p">(</span><span class="n">bytes_to_long</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">"g.enc"</span><span class="p">,</span><span class="s">"rb"</span><span class="p">).</span><span class="n">read</span><span class="p">())</span> <span class="p">,</span><span class="mi">5</span><span class="p">))</span>
<span class="n">g</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">g</span><span class="p">]</span>
<span class="c1"># Step 2
</span><span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="p">[</span><span class="n">g</span><span class="p">]:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">65791</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span> <span class="n">_</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-=</span> <span class="n">_</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="n">c</span><span class="p">]</span>
<span class="c1"># Step 3
</span><span class="n">f</span> <span class="o">=</span> <span class="n">g</span><span class="p">[</span><span class="mi">67</span><span class="p">:</span><span class="mi">67</span><span class="o">+</span><span class="mi">256</span><span class="p">]</span>
<span class="n">f</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">f</span><span class="p">]</span>
<span class="c1"># Step 4
</span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span><span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-=</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">f</span><span class="p">]))</span>
</code></pre></div></div>
<h5 id="flag-2">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{_how_finD_7h1s_1z_s3cr3T?!}</code></p>
<h2 id="symbols">Symbols</h2>
<h3 id="challenge-3">Challenge</h3>
<blockquote>
<p>Oh, my eyes, my eyes! People still can solve this kind of cryptography? Mathematicians should love this one!
<img src="/assets/images/cryptoctf-symbols.png" alt="Symbols Challenge" /></p>
</blockquote>
<h3 id="solution-3">Solution</h3>
<p>In this challenge, we are given an image of math symbols, from the first couple of symbols and the flag format, we can guess that the flag is the initials of these symbols in $\LaTeX$.</p>
<p>By using Mathpix Snip, a tool that can convert images into LaTeX for inline equations, we can get most of the symbols and get the flag.</p>
\[\Cap \Cap \Theta \Finv \{ \Pi \ltimes \aleph y \_ \wp \infty \therefore \heartsuit \_ \Lsh \aleph \Theta \eth \Xi \}\]
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\Cap \Cap \Theta \Finv \{ \Pi \ltimes \aleph y \_ \wp \infty \therefore \heartsuit \_ \Lsh \aleph \Theta \eth \Xi \}
</code></pre></div></div>
<h5 id="flag-3">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{Play_with_LaTeX}</code></p>
<h2 id="hyper-normal">Hyper Normal</h2>
<h3 id="challenge-4">Challenge</h3>
<blockquote>
<p>Being normal is hard these days because of Corona virus pandemic!</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">FLAG</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">8443</span>
<span class="k">def</span> <span class="nf">transpose</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="n">result</span> <span class="o">=</span> <span class="p">[[</span><span class="n">x</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">))]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]))]</span>
<span class="k">return</span> <span class="n">result</span>
<span class="k">def</span> <span class="nf">vsum</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">):</span>
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">u</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="n">l</span><span class="p">,</span> <span class="n">w</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">u</span><span class="p">),</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">w</span> <span class="o">+=</span> <span class="p">[(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">v</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">%</span> <span class="n">p</span><span class="p">]</span>
<span class="k">return</span> <span class="n">w</span>
<span class="k">def</span> <span class="nf">sprod</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">u</span><span class="p">):</span>
<span class="n">w</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">u</span><span class="p">)):</span>
<span class="n">w</span> <span class="o">+=</span> <span class="p">[</span><span class="n">a</span><span class="o">*</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">%</span> <span class="n">p</span><span class="p">]</span>
<span class="k">return</span> <span class="n">w</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="n">hyper</span> <span class="o">=</span> <span class="p">[</span><span class="nb">ord</span><span class="p">(</span><span class="n">m</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">msg</span><span class="p">),</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">))]</span>
<span class="n">V</span><span class="p">,</span> <span class="n">W</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">v</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">i</span> <span class="o">+</span> <span class="p">[</span><span class="n">hyper</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span> <span class="o">+</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="p">(</span><span class="n">l</span> <span class="o">-</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">V</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="n">random</span><span class="p">.</span><span class="n">shuffle</span><span class="p">(</span><span class="n">V</span><span class="p">)</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">R</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="p">[</span><span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">126</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">)],</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">l</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">vsum</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">sprod</span><span class="p">(</span><span class="n">R</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">V</span><span class="p">[</span><span class="n">j</span><span class="p">]))</span>
<span class="n">W</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="n">random</span><span class="p">.</span><span class="n">shuffle</span><span class="p">(</span><span class="n">transpose</span><span class="p">(</span><span class="n">W</span><span class="p">))</span>
<span class="k">return</span> <span class="n">W</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">enc</span><span class="p">)</span>
</code></pre></div></div>
<h3 id="solution-4">Solution</h3>
<p>This challenge gives a strange encryption scheme. This encryption algorithm actually does this. For an input of length $l$, the algorithm first multiplies each character of the input by the corresponding index to obtain a vector $x$. Then the algorithm loops $l$ times, each time outputs a vector $v$. Each number in the vector $v$ is a random number between 0 and 126 multiplied by the corresponding number in the vector $x$. All these operations are performed modulo 8443.</p>
<p>It is worth noting that <code class="language-plaintext highlighter-rouge">random.shuffle</code> on line 38 of the program actually has no effect on the output, because the <code class="language-plaintext highlighter-rouge">transpose</code> function returns a new object.</p>
<p>Solving for the input is intuitive. For the i-th byte of the input, we simply iterate through all printable characters, multiply $i$ by those characters, and multiply 0 through 126 to get all possible results. If column $i$ of the program output happens to be a subset of the possible results generated by a character $c$, then the i-th byte of the input is likely to be $c$.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">string</span> <span class="kn">import</span> <span class="n">printable</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">8443</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'output.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">enc</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">())</span>
<span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">enc</span><span class="p">[</span><span class="mi">0</span><span class="p">])):</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">enc</span><span class="p">:</span>
<span class="n">tmp</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">j</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
<span class="n">results</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">tmp</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">result</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">results</span><span class="p">):</span>
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">printable</span><span class="p">:</span>
<span class="n">possibilities</span> <span class="o">=</span> <span class="p">[</span><span class="nb">ord</span><span class="p">(</span><span class="n">c</span><span class="p">)</span><span class="o">*</span><span class="n">i</span><span class="o">*</span><span class="p">(</span><span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">127</span><span class="p">)]</span>
<span class="k">if</span> <span class="nb">all</span><span class="p">([</span><span class="n">i</span> <span class="ow">in</span> <span class="n">possibilities</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">result</span><span class="p">]):</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="n">c</span>
<span class="k">break</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</code></pre></div></div>
<h5 id="flag-4">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{H0w_f1Nd_th3_4lL_3I9EnV4Lu35_iN_FiN173_Fi3lD5!???}</code></p>
<h2 id="salt-and-pepper">Salt and Pepper</h2>
<h3 id="challenge-5">Challenge</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="n">md5</span><span class="p">,</span> <span class="n">sha1</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">salt</span><span class="p">,</span> <span class="n">pepper</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">salt</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">pepper</span><span class="p">)</span> <span class="o">==</span> <span class="mi">19</span>
<span class="k">assert</span> <span class="n">md5</span><span class="p">(</span><span class="n">salt</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">()</span> <span class="o">==</span> <span class="s">'5f72c4360a2287bc269e0ccba6fc24ba'</span>
<span class="k">assert</span> <span class="n">sha1</span><span class="p">(</span><span class="n">pepper</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">()</span> <span class="o">==</span> <span class="s">'3e0d000a4b0bd712999d730bc331f400221008e0'</span>
<span class="k">def</span> <span class="nf">auth_check</span><span class="p">(</span><span class="n">salt</span><span class="p">,</span> <span class="n">pepper</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">h</span><span class="p">):</span>
<span class="k">return</span> <span class="n">sha1</span><span class="p">(</span><span class="n">pepper</span> <span class="o">+</span> <span class="n">password</span> <span class="o">+</span> <span class="n">md5</span><span class="p">(</span><span class="n">salt</span> <span class="o">+</span> <span class="n">username</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">().</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)).</span><span class="n">hexdigest</span><span class="p">()</span> <span class="o">==</span> <span class="n">h</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" welcome to hash killers battle, your mission is to login into the "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" ultra secure authentication server with provided information!! "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">USERNAME</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'n3T4Dm1n'</span>
<span class="n">PASSWORD</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'P4s5W0rd'</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[L]ogin to server </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'l'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| send your username, password as hex string separated with comma: '</span><span class="p">)</span>
<span class="n">inp</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">inp_username</span><span class="p">,</span> <span class="n">inp_password</span> <span class="o">=</span> <span class="p">[</span><span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">inp</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)]</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| your input is not valid, bye!!'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| send your authentication hash: '</span><span class="p">)</span>
<span class="n">inp_hash</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">if</span> <span class="n">USERNAME</span> <span class="ow">in</span> <span class="n">inp_username</span> <span class="ow">and</span> <span class="n">PASSWORD</span> <span class="ow">in</span> <span class="n">inp_password</span><span class="p">:</span>
<span class="k">if</span> <span class="n">auth_check</span><span class="p">(</span><span class="n">salt</span><span class="p">,</span> <span class="n">pepper</span><span class="p">,</span> <span class="n">inp_username</span><span class="p">,</span> <span class="n">inp_password</span><span class="p">,</span> <span class="n">inp_hash</span><span class="p">):</span>
<span class="n">die</span><span class="p">(</span><span class="sa">f</span><span class="s">'| Congrats, you are master in hash killing, and it is the flag: </span><span class="si">{</span><span class="n">flag</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| your credential is not valid, Bye!!!'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| Kidding me?! Bye!!!'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<p>We send a username and password to the server, along with an authentication hash. These are all passed as parameters to the <code class="language-plaintext highlighter-rouge">auth_check</code> function, and the username contains<code class="language-plaintext highlighter-rouge">n3T4Dm1n</code>, the password contains <code class="language-plaintext highlighter-rouge">P4s5W0rd</code>, and the function returns true, we get the flag.</p>
<h3 id="solution-5">Solution</h3>
<p>The <code class="language-plaintext highlighter-rouge">check_auth</code> function uses two secrets, <code class="language-plaintext highlighter-rouge">salt</code> and <code class="language-plaintext highlighter-rouge">pepper</code>, which we know the length of, however we don’t know the value of.</p>
<p>The <code class="language-plaintext highlighter-rouge">check_auth</code> function calculates the authentication hash using the following line</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sha1</span><span class="p">(</span><span class="n">pepper</span> <span class="o">+</span> <span class="n">password</span> <span class="o">+</span> <span class="n">md5</span><span class="p">(</span><span class="n">salt</span> <span class="o">+</span> <span class="n">username</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">().</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)).</span><span class="n">hexdigest</span><span class="p">()</span>
</code></pre></div></div>
<p>Since these two secrets are hashed as well as our username and password, we cannot directly work out the authentication hash. However, we get given the MD5 hash of <code class="language-plaintext highlighter-rouge">salt</code>, and the SHA1 hash of <code class="language-plaintext highlighter-rouge">pepper</code>. Since both of the secret values are put as prefixes to our input, we can perform a hash length extension attack.</p>
<p><a href="https://github.com/bwall/HashPump">HashPump</a> is a useful tool to do this, as all we need to do is provide the parameters and the tool does most of the work for us. One thing that needed to be changed however is that since we get the raw hashes, we don’t have any data to give to the tool, and Hashpump complains when we do that.</p>
<p>To get around this, I simply removed this check in the <code class="language-plaintext highlighter-rouge">main.cpp</code> file (line 255) and recompiled it.</p>
<p>First, we will create a MD5 of (<code class="language-plaintext highlighter-rouge">salt</code> + <code class="language-plaintext highlighter-rouge">padding</code> + <code class="language-plaintext highlighter-rouge">n3T4Dm1n</code>) using the tool:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hashpump -s "5f72c4360a2287bc269e0ccba6fc24ba" -d "" -a "n3T4Dm1n" -k 19
</code></pre></div></div>
<p>giving an output of</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>95623660d3d04c7680a52679e35f041c
\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x00\x00\x00\x00\x00\x00\x00n3T4Dm1n
</code></pre></div></div>
<p>Then, we will create our authentication hash by creating a SHA1 of (<code class="language-plaintext highlighter-rouge">pepper</code> + <code class="language-plaintext highlighter-rouge">padding</code> + <code class="language-plaintext highlighter-rouge">P4s5W0rd</code> + <code class="language-plaintext highlighter-rouge">95623660d3d04c7680a52679e35f041c</code>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hashpump -s "3e0d000a4b0bd712999d730bc331f400221008e0" -d "" -a "P4s5W0rd95623660d3d04c7680a52679e35f041c" -k 19
</code></pre></div></div>
<p>giving an output of</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>83875efbe020ced3e2c5ecc908edc98481eba47f
\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98P4s5W0rd95623660d3d04c7680a52679e35f041c
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">83875efbe020ced3e2c5ecc908edc98481eba47f</code> should now be our authentication hash when we use <code class="language-plaintext highlighter-rouge">\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x00\x00\x00\x00\x00\x00\x00n3T4Dm1n</code> as our username and <code class="language-plaintext highlighter-rouge">\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98P4s5W0rd</code> as our password (note that we remove the MD5 hash at the end as it gets added when the <code class="language-plaintext highlighter-rouge">auth_check</code> function is called).</p>
<p>Submitting these to the server gives us the flag.</p>
<h5 id="flag-5">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{Hunters_Killed_82%_More_Wolves_Than_Quota_Allowed_in_Wisconsin}</code></p>
<h2 id="titu">Titu</h2>
<h3 id="challenge-6">Challenge</h3>
<blockquote>
<p><a href="https://cr.yp.toc.tf/tasks/Tuti_f9ebebb92f31b4eaefdb6491bdcd7a9c008ad2ec.txz">Cryptography</a> is coupled with all kinds of equations very much!</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">m_1</span><span class="p">,</span> <span class="n">m_2</span> <span class="o">=</span> <span class="n">flag</span><span class="p">[:</span> <span class="n">l</span> <span class="o">//</span> <span class="mi">2</span><span class="p">],</span> <span class="n">flag</span><span class="p">[</span><span class="n">l</span> <span class="o">//</span> <span class="mi">2</span><span class="p">:]</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">m_1</span><span class="p">),</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">m_2</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="s">'''
000bfdc32162934ad6a054b4b3db8578674e27a165113f8ed018cbe9112
4fbd63144ab6923d107eee2bc0712fcbdb50d96fdf04dd1ba1b69cb1efe
71af7ca08ddc7cc2d3dfb9080ae56861d952e8d5ec0ba0d3dfdf2d12764
'''</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
<span class="k">assert</span><span class="p">((</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span><span class="o">*</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span> <span class="o">+</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="p">))</span>
</code></pre></div></div>
<p>Given this source, the goal is to solve the equation to obtain both $x,y$.</p>
<h3 id="solution-6">Solution</h3>
<p>Factoring $k$ we find that it is a perfect square</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sage</span><span class="p">:</span> <span class="n">factor</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="mi">2</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">11</span><span class="o">^</span><span class="mi">4</span> <span class="o">*</span> <span class="mi">19</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">47</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">71</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3449</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">11953</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">5485619</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">2035395403834744453</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">17258104558019725087</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">1357459302115148222329561139218955500171643099</span><span class="o">^</span><span class="mi">2</span>
</code></pre></div></div>
<p>Which tells us that moving some terms around, we can write the left hand side as a perfect square too:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sage</span><span class="p">:</span> <span class="n">f</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-</span> <span class="mi">4</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">y</span>
<span class="n">sage</span><span class="p">:</span> <span class="n">f</span>
<span class="n">x</span><span class="o">^</span><span class="mi">2</span><span class="o">*</span><span class="n">y</span><span class="o">^</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">x</span><span class="o">^</span><span class="mi">2</span><span class="o">*</span><span class="n">y</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="o">^</span><span class="mi">2</span> <span class="o">+</span> <span class="n">x</span><span class="o">^</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">4</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">y</span> <span class="o">+</span> <span class="n">y</span><span class="o">^</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">x</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">y</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">sage</span><span class="p">:</span> <span class="n">factor</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="p">(</span><span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">^</span><span class="mi">2</span>
</code></pre></div></div>
<p>So we can solve this challenge by looking at the divisors of $\sqrt{4k}$ as we have</p>
\[(y - 1)^2 (x + 1)^2 = 4k = m\]
<p>This is easy using Sage’s <code class="language-plaintext highlighter-rouge">divisors(m)</code> function:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">factors</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">47</span><span class="p">,</span> <span class="mi">71</span><span class="p">,</span> <span class="mi">3449</span><span class="p">,</span> <span class="mi">11953</span><span class="p">,</span> <span class="mi">5485619</span><span class="p">,</span> <span class="mi">2035395403834744453</span><span class="p">,</span> <span class="mi">17258104558019725087</span><span class="p">,</span> <span class="mi">1357459302115148222329561139218955500171643099</span><span class="p">]</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">prod</span><span class="p">(</span><span class="n">factors</span><span class="p">)</span>
<span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">divs</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">d</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">'CCTF{'</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="n">n</span> <span class="o">//</span> <span class="n">d</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">y</span><span class="p">))</span>
<span class="sa">b</span><span class="s">'CCTF{S1mPL3_4Nd_N!cE_D'</span>
<span class="sa">b</span><span class="s">'iophantine_EqUa7I0nS!}'</span>
</code></pre></div></div>
<h5 id="flag-6">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{S1mPL3_4Nd_N!cE_Diophantine_EqUa7I0nS!}</code></p>
<h2 id="hamul">Hamul</h2>
<h3 id="challenge-7">Challenge</h3>
<blockquote>
<p>RSA could be hard, or easy?</p>
<ul>
<li><a href="https://cr.yp.toc.tf/tasks/hamul_e420933a0655ea08209d1fe9588ba8a3a6db6bf5.txz">hamul_e420933a0655ea08209d1fe9588ba8a3a6db6bf5.txz.txz</a></li>
</ul>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="n">nbit</span> <span class="o">=</span> <span class="mi">64</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">getPrime</span><span class="p">(</span><span class="n">nbit</span><span class="p">),</span> <span class="n">getPrime</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span>
<span class="n">P</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">q</span><span class="p">))</span>
<span class="n">Q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">q</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">))</span>
<span class="n">PP</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">P</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">Q</span><span class="p">))</span>
<span class="n">QQ</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">Q</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">P</span><span class="p">))</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">PP</span><span class="p">)</span> <span class="ow">and</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">QQ</span><span class="p">):</span>
<span class="k">break</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">PP</span> <span class="o">*</span> <span class="n">QQ</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">flag</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="k">if</span> <span class="n">m</span> <span class="o"><</span> <span class="n">n</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="mi">65537</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'n ='</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'c ='</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>
<span class="c1"># n = 98027132963374134222724984677805364225505454302688777506193468362969111927940238887522916586024601699661401871147674624868439577416387122924526713690754043
# c = 42066148309824022259115963832631631482979698275547113127526245628391950322648581438233116362337008919903556068981108710136599590349195987128718867420453399
</span></code></pre></div></div>
<h3 id="solution-7">Solution</h3>
<p>Since we can see that the generation of $PP$ and $QQ$ is special:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">getPrime</span><span class="p">(</span><span class="n">nbit</span><span class="p">),</span> <span class="n">getPrime</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span>
<span class="n">P</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">q</span><span class="p">))</span>
<span class="n">Q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">q</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">))</span>
<span class="n">PP</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">P</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">Q</span><span class="p">))</span>
<span class="n">QQ</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">Q</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">P</span><span class="p">))</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">PP</span><span class="p">)</span> <span class="ow">and</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">QQ</span><span class="p">):</span>
<span class="k">break</span>
</code></pre></div></div>
<p>If we let <code class="language-plaintext highlighter-rouge">x, y = len(str(p)), len(str(q))</code>, we will get:</p>
\[P = 10^{x}p + q,\, Q = 10^{y}q + p\]
<p>Also we let <code class="language-plaintext highlighter-rouge">x', y' = len(str(P)), len(str(Q))</code>, we will get:</p>
\[PP = 10^{x'}P+Q,\, QQ=10^{y'}Q+P\]
<p>After we put $P = 10^{x}p + q,\, Q = 10^{y}q + p$ into the above equation and calculate</p>
\[N=PP \cdot QQ\]
<p>we will find $N$ looks like in this form:</p>
\[N = 10^{x+x'+y+y'}pq + \ldots +pq\]
<p>Since $x+x’+y+y’$ is big enough, so we know that <code class="language-plaintext highlighter-rouge">str(N)[:?]</code> is actually <code class="language-plaintext highlighter-rouge">str(pq)[:?]</code> and as the same, <code class="language-plaintext highlighter-rouge">str(N)[?:]</code> is actually <code class="language-plaintext highlighter-rouge">str(pq)[?:]</code>.</p>
<p>After generating my own testcase, I find that <code class="language-plaintext highlighter-rouge">str(N)[:18] = str(pq)[:?]</code>, <code class="language-plaintext highlighter-rouge">str(N)[-18:] = str(pq)[-18:]</code> and actually <code class="language-plaintext highlighter-rouge">len(str(p*q)) = 38</code> so we just need brute force 2 number between the high-part and low-part.</p>
<p>So we can get $pq$ and factor it to get $p$ and $q$. The next is simple decryption.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">tqdm</span> <span class="kn">import</span> <span class="n">tqdm</span>
<span class="k">def</span> <span class="nf">decrypt_RSA</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">):</span>
<span class="n">phi</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">inverse</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">phi</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span><span class="o">*</span><span class="n">q</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">m</span><span class="p">))</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">98027132963374134222724984677805364225505454302688777506193468362969111927940238887522916586024601699661401871147674624868439577416387122924526713690754043</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">42066148309824022259115963832631631482979698275547113127526245628391950322648581438233116362337008919903556068981108710136599590349195987128718867420453399</span>
<span class="n">low</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">n</span><span class="p">)[</span><span class="o">-</span><span class="mi">18</span><span class="p">:]</span>
<span class="n">high</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">n</span><span class="p">)[:</span><span class="mi">18</span><span class="p">]</span>
<span class="n">pq_prob</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">pq_prob</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">high</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">j</span><span class="p">)</span><span class="o">+</span> <span class="n">low</span><span class="p">))</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">tqdm</span><span class="p">(</span><span class="n">pq_prob</span><span class="p">):</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">factor</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">].</span><span class="n">nbits</span><span class="p">()</span> <span class="o">==</span> <span class="mi">64</span><span class="p">):</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">f</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="k">break</span>
<span class="n">P</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">q</span><span class="p">))</span>
<span class="n">Q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">q</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">p</span><span class="p">))</span>
<span class="n">PP</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">P</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">Q</span><span class="p">))</span>
<span class="n">QQ</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">Q</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">P</span><span class="p">))</span>
<span class="n">N</span> <span class="o">=</span> <span class="n">PP</span> <span class="o">*</span> <span class="n">QQ</span>
<span class="k">print</span><span class="p">(</span><span class="n">N</span> <span class="o">==</span> <span class="n">n</span><span class="p">)</span>
<span class="n">decrypt_RSA</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mi">65537</span><span class="p">,</span> <span class="n">PP</span><span class="p">,</span> <span class="n">QQ</span><span class="p">)</span>
</code></pre></div></div>
<h5 id="flag-7">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{wH3Re_0Ur_Br41N_Iz_5uP3R_4CtIVe_bY_RSA!!}</code></p>["CryptoHackers"]Last week, CryptoHackers got together to play CryptoCTF for the second time as a team. We solved 26/29 of the challenges during the 24 hour window and came third overall. First and second places went to Super Guessers (Rkm and Rbtree are very friendly faces from CryptoHack) and a Vietnamese team working together to support the spirit of Ho Chi Minh city and nearby provinces. Congratulations to them both.CryptoCTF 2021 - Medium2021-08-05T00:00:00+00:002021-08-05T00:00:00+00:00https://blog.cryptohack.org/cryptoctf-medium<p>Last week, CryptoHackers got together to play CryptoCTF for the second time as a team. We solved 26/29 of the challenges during the 24 hour window and came third overall. First and second places went to Super Guessers (Rkm and Rbtree are very friendly faces from CryptoHack) and a Vietnamese team working together to support the spirit of Ho Chi Minh city and nearby provinces. Congratulations to them both.</p>
<p><img src="/assets/images/cryptoctf-2021.png" alt="CTF Scoreboard" /></p>
<p>Not only was it a lot of fun for us all to play together, but it was amazing to see how many CryptoHack friends played the CTF either solo or in small teams and who were able to get a top 15 spot. We’re honoured to have so many talented people in our Discord, chatting with us about maths and cryptography. We even have guest writeups from <a href="https://rkm0959.tistory.com">rkm0959</a> talking about the solutions of <a href="https://blog.cryptohack.org/cryptoctf2021-hard#dorsa">DoRSA</a> and <a href="https://blog.cryptohack.org/cryptoctf2021-hard#polish">Polish</a></p>
<p>Here are the write-ups for the middle-difficulty challenges in the CTF. You can find write ups for the <a href="https://blog.cryptohack.org/cryptoctf2021-easy">easy</a> and <a href="https://blog.cryptohack.org/cryptoctf2021-hard">hard</a> challenges as other posts on our blog.</p>
<p>Thank you to everyone who played for the CryptoHackers, and to ASIS CTF for organising this enjoyable event. Congratulations again to Super Guessers for being the ultimate crypto heros!</p>
<p><em>We will be publishing more writeups here as soon as they are finished. If you spot a mistake or an improvement that could be made, please ping jack or hyperreality on CryptoHack Discord.</em></p>
<h2 id="challenges">Challenges</h2>
<table>
<thead>
<tr>
<th>Challenge Name</th>
<th>Category</th>
<th>Solved By</th>
<th style="text-align: right">Points</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#triplet">Triplet</a></td>
<td>RSA</td>
<td>Willwam845, Retroid, Vishiswoz</td>
<td style="text-align: right">91</td>
</tr>
<tr>
<td><a href="#onlude">Onlude</a></td>
<td>Linear algebra</td>
<td>Q7</td>
<td style="text-align: right">95</td>
</tr>
<tr>
<td><a href="#improved">Improved</a></td>
<td>Asymmetric Collisions</td>
<td>Willwam845, Vishiswoz (Coming Soon)</td>
<td style="text-align: right">117</td>
</tr>
<tr>
<td><a href="#maid">Maid</a></td>
<td>Rabin Cryptosystem</td>
<td>Defund</td>
<td style="text-align: right">119</td>
</tr>
<tr>
<td><a href="#wolf">Wolf</a></td>
<td>AES-GCM</td>
<td>DD</td>
<td style="text-align: right">128</td>
</tr>
<tr>
<td><a href="#ferman">Ferman</a></td>
<td>Mathematics</td>
<td>Jack</td>
<td style="text-align: right">134</td>
</tr>
<tr>
<td><a href="#rsaphantine">RSAphantine</a></td>
<td>Diophantine Equations</td>
<td>AC, UnblvR, Jack</td>
<td style="text-align: right">142</td>
</tr>
<tr>
<td><a href="#frozen">Frozen</a></td>
<td>Signature Schemes</td>
<td>DD</td>
<td style="text-align: right">142</td>
</tr>
<tr>
<td><a href="#linda">LINDA</a></td>
<td>Discrete logarithm</td>
<td>NeketmanX</td>
<td style="text-align: right">169</td>
</tr>
</tbody>
</table>
<h2 id="triplet">Triplet</h2>
<h3 id="challenge">Challenge</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">FLAG</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" hi talented cryptographers, the mission is to find the three RSA "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" modulus with the same public and private exponent! Try your chance!"</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">nbit</span> <span class="o">=</span> <span class="mi">160</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[S]end the three nbit prime pairs </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="n">order</span> <span class="o">=</span> <span class="p">[</span><span class="s">'first'</span><span class="p">,</span> <span class="s">'second'</span><span class="p">,</span> <span class="s">'third'</span><span class="p">]</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'s'</span><span class="p">:</span>
<span class="n">P</span><span class="p">,</span> <span class="n">N</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Send the "</span> <span class="o">+</span> <span class="n">order</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="s">" RSA primes such that nbit >= "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span> <span class="o">+</span> <span class="s">": p_"</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="s">", q_"</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="s">" "</span><span class="p">)</span>
<span class="n">params</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">params</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your primes are not valid!!"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="ow">and</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">q</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">p</span><span class="p">)[</span><span class="mi">2</span><span class="p">:])</span> <span class="o">>=</span> <span class="n">nbit</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">q</span><span class="p">)[</span><span class="mi">2</span><span class="p">:])</span> <span class="o">>=</span> <span class="n">nbit</span><span class="p">:</span>
<span class="n">P</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">))</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="n">N</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your input is not desired prime, Bye!"</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">N</span><span class="p">))</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Send the public and private exponent: e, d "</span><span class="p">)</span>
<span class="n">params</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">e</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">params</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)</span>
<span class="n">e</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">e</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your parameters are not valid!! Bye!!!"</span><span class="p">)</span>
<span class="n">phi_1</span> <span class="o">=</span> <span class="p">(</span><span class="n">P</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">P</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">phi_2</span> <span class="o">=</span> <span class="p">(</span><span class="n">P</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">P</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">phi_3</span> <span class="o">=</span> <span class="p">(</span><span class="n">P</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">P</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="mi">1</span> <span class="o"><</span> <span class="n">e</span> <span class="o"><</span> <span class="nb">min</span><span class="p">([</span><span class="n">phi_1</span><span class="p">,</span> <span class="n">phi_2</span><span class="p">,</span> <span class="n">phi_3</span><span class="p">])</span> <span class="ow">and</span> <span class="mi">1</span> <span class="o"><</span> <span class="n">d</span> <span class="o"><</span> <span class="nb">min</span><span class="p">([</span><span class="n">phi_1</span><span class="p">,</span> <span class="n">phi_2</span><span class="p">,</span> <span class="n">phi_3</span><span class="p">]):</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span> <span class="n">d</span> <span class="o">%</span> <span class="n">phi_1</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span> <span class="n">d</span> <span class="o">%</span> <span class="n">phi_2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span> <span class="n">d</span> <span class="o">%</span> <span class="n">phi_3</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">b</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| You got the flag:"</span><span class="p">,</span> <span class="n">FLAG</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| invalid exponents, bye!!!"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| the exponents are too small or too large!"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| kidding me?!!, bye!"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<p>We need to send 3 pairs of primes followed by a keypair <code class="language-plaintext highlighter-rouge">e,d</code> so that <code class="language-plaintext highlighter-rouge">e,d</code> is a valid keypair for each modulus generated by each pair.</p>
<p>Most easy solutions are patched out, as <code class="language-plaintext highlighter-rouge">e</code> and <code class="language-plaintext highlighter-rouge">d</code> both have to be less than the lowest phi and greater than 1.</p>
<h3 id="solution">Solution</h3>
<p>Our main idea for this problem is to generate <code class="language-plaintext highlighter-rouge">phi_1</code>, <code class="language-plaintext highlighter-rouge">phi_2</code> and <code class="language-plaintext highlighter-rouge">phi_3</code> in a way so that <code class="language-plaintext highlighter-rouge">phi_2</code> is a multiple of <code class="language-plaintext highlighter-rouge">phi_1</code>, and <code class="language-plaintext highlighter-rouge">phi_3</code> is a multiple of <code class="language-plaintext highlighter-rouge">phi_2</code>. In this way, any valid keypair for <code class="language-plaintext highlighter-rouge">phi_3</code> (that also satisfies the length requirement) will also be a valid keypair for <code class="language-plaintext highlighter-rouge">phi_1</code> and <code class="language-plaintext highlighter-rouge">phi_2</code> and can be used to get the flag.</p>
<p>We can generate primes as follows:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">phi</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="n">q</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randrange</span>
<span class="k">def</span> <span class="nf">genprime</span><span class="p">(</span><span class="n">baseprime</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">randrange</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1000</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">baseprime</span> <span class="o">*</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
<span class="k">return</span> <span class="n">p</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">random_prime</span><span class="p">(</span><span class="mi">2</span><span class="o">^</span><span class="mi">160</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">random_prime</span><span class="p">(</span><span class="mi">2</span><span class="o">^</span><span class="mi">160</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">genprime</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">genprime</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">genprime</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
<span class="n">u</span> <span class="o">=</span> <span class="n">genprime</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="n">phi_1</span> <span class="o">=</span> <span class="n">phi</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="n">q</span><span class="p">)</span>
<span class="n">phi_2</span> <span class="o">=</span> <span class="n">phi</span><span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">s</span><span class="p">)</span>
<span class="n">phi_3</span> <span class="o">=</span> <span class="n">phi</span><span class="p">(</span><span class="n">t</span><span class="p">,</span><span class="n">u</span><span class="p">)</span>
</code></pre></div></div>
<p>Now all we need to do is generate a valid keypair for <code class="language-plaintext highlighter-rouge">phi_3</code>. To do this, recall that the values $e$ and $d$ satisfy the following equation:</p>
\[e * d \equiv 1 \mod \phi(n)\]
<p>therefore</p>
\[e * d = 1 + k * \phi(n)\]
<p>If we find factors of $1 + phi(n3)$, we should be able to find two numbers that are small enough to satisfy the length requirements, as the value $k$ in the equation</p>
\[\phi(n3) = k * \phi(n1)\]
<p>should be small. We can just use something like <a href="http://factordb.com/">factordb</a> for this.</p>
<p>Once we do that, we submit everything to the server and get our flag.</p>
<p>Example input:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1016528131013635090619361217720494946552931485213,1429584882448210886669728733194710184148915763157
6211546314237476302579971345731015750127038990912821,8860059189914843449838352373651833954155350825107793
9404281119755539122106076617436757845692337032242009481,24063920759808714809760965046838381019485932840992763073
43589288709210633359625764026901174390804401096987086682930362519465081895858044399533,5191731325979249818708517
</code></pre></div></div>
<h5 id="flag">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{7HrE3_b4Bie5_c4rRi3d_dUr1nG_0Ne_pr39naNcY_Ar3_triplets}</code></p>
<h2 id="onlude">Onlude</h2>
<h3 id="challenge-1">Challenge</h3>
<blockquote>
<p>Encryption and Decryption could be really easy, while we expected the decryption to be harder!</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env sage
</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">global</span> <span class="n">p</span><span class="p">,</span> <span class="n">alphabet</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">71</span>
<span class="n">alphabet</span> <span class="o">=</span> <span class="s">'=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$!?_{}<>'</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">flag</span><span class="p">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">'CCTF{'</span><span class="p">).</span><span class="n">rstrip</span><span class="p">(</span><span class="s">'}'</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span> <span class="o">==</span> <span class="mi">24</span>
<span class="k">def</span> <span class="nf">cross</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
<span class="k">return</span> <span class="n">alphabet</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
<span class="n">A</span> <span class="o">=</span> <span class="n">zero_matrix</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">msg</span><span class="p">)):</span>
<span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">5</span><span class="o">*</span><span class="n">k</span> <span class="o">//</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">5</span><span class="o">*</span><span class="n">k</span> <span class="o">%</span> <span class="mi">11</span>
<span class="n">A</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">cross</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="n">k</span><span class="p">])</span>
<span class="k">return</span> <span class="n">A</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">():</span>
<span class="n">R</span> <span class="o">=</span> <span class="n">random_matrix</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">S</span> <span class="o">=</span> <span class="n">random_matrix</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span>
<span class="k">if</span> <span class="n">S</span><span class="p">.</span><span class="n">rank</span><span class="p">()</span> <span class="o">==</span> <span class="mi">11</span><span class="p">:</span>
<span class="n">_</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">U</span> <span class="o">=</span> <span class="n">S</span><span class="p">.</span><span class="n">LU</span><span class="p">()</span>
<span class="k">return</span> <span class="n">R</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">U</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="n">R</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">U</span> <span class="o">=</span> <span class="n">key</span>
<span class="n">S</span> <span class="o">=</span> <span class="n">L</span> <span class="o">*</span> <span class="n">U</span>
<span class="n">X</span> <span class="o">=</span> <span class="n">A</span> <span class="o">+</span> <span class="n">R</span>
<span class="n">Y</span> <span class="o">=</span> <span class="n">S</span> <span class="o">*</span> <span class="n">X</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">L</span><span class="p">.</span><span class="n">inverse</span><span class="p">()</span> <span class="o">*</span> <span class="n">Y</span>
<span class="k">return</span> <span class="n">E</span>
<span class="n">A</span> <span class="o">=</span> <span class="n">prepare</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">()</span>
<span class="n">R</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">U</span> <span class="o">=</span> <span class="n">key</span>
<span class="n">S</span> <span class="o">=</span> <span class="n">L</span> <span class="o">*</span> <span class="n">U</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'E = </span><span class="se">\n</span><span class="si">{</span><span class="n">E</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'L * U * L = </span><span class="se">\n</span><span class="si">{</span><span class="n">L</span> <span class="o">*</span> <span class="n">U</span> <span class="o">*</span> <span class="n">L</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'L^(-1) * S^2 * L = </span><span class="se">\n</span><span class="si">{</span><span class="n">L</span><span class="p">.</span><span class="n">inverse</span><span class="p">()</span> <span class="o">*</span> <span class="n">S</span><span class="o">**</span><span class="mi">2</span> <span class="o">*</span> <span class="n">L</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'R^(-1) * S^8 = </span><span class="se">\n</span><span class="si">{</span><span class="n">R</span><span class="p">.</span><span class="n">inverse</span><span class="p">()</span> <span class="o">*</span> <span class="n">S</span><span class="o">**</span><span class="mi">8</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">E</span> <span class="o">=</span>
<span class="p">[</span><span class="mi">25</span> <span class="mi">55</span> <span class="mi">61</span> <span class="mi">28</span> <span class="mi">11</span> <span class="mi">46</span> <span class="mi">19</span> <span class="mi">50</span> <span class="mi">37</span> <span class="mi">5</span> <span class="mi">21</span><span class="p">]</span>
<span class="p">[</span><span class="mi">20</span> <span class="mi">57</span> <span class="mi">39</span> <span class="mi">9</span> <span class="mi">25</span> <span class="mi">37</span> <span class="mi">63</span> <span class="mi">31</span> <span class="mi">70</span> <span class="mi">15</span> <span class="mi">47</span><span class="p">]</span>
<span class="p">[</span><span class="mi">56</span> <span class="mi">31</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">50</span> <span class="mi">67</span> <span class="mi">38</span> <span class="mi">14</span> <span class="mi">42</span> <span class="mi">46</span> <span class="mi">14</span><span class="p">]</span>
<span class="p">[</span><span class="mi">42</span> <span class="mi">54</span> <span class="mi">38</span> <span class="mi">22</span> <span class="mi">19</span> <span class="mi">55</span> <span class="mi">7</span> <span class="mi">18</span> <span class="mi">45</span> <span class="mi">53</span> <span class="mi">39</span><span class="p">]</span>
<span class="p">[</span><span class="mi">55</span> <span class="mi">26</span> <span class="mi">42</span> <span class="mi">15</span> <span class="mi">48</span> <span class="mi">6</span> <span class="mi">24</span> <span class="mi">4</span> <span class="mi">17</span> <span class="mi">60</span> <span class="mi">64</span><span class="p">]</span>
<span class="p">[</span> <span class="mi">1</span> <span class="mi">38</span> <span class="mi">50</span> <span class="mi">10</span> <span class="mi">19</span> <span class="mi">57</span> <span class="mi">26</span> <span class="mi">48</span> <span class="mi">6</span> <span class="mi">4</span> <span class="mi">14</span><span class="p">]</span>
<span class="p">[</span><span class="mi">13</span> <span class="mi">4</span> <span class="mi">38</span> <span class="mi">54</span> <span class="mi">23</span> <span class="mi">34</span> <span class="mi">54</span> <span class="mi">42</span> <span class="mi">15</span> <span class="mi">56</span> <span class="mi">29</span><span class="p">]</span>
<span class="p">[</span><span class="mi">26</span> <span class="mi">66</span> <span class="mi">8</span> <span class="mi">48</span> <span class="mi">6</span> <span class="mi">70</span> <span class="mi">44</span> <span class="mi">8</span> <span class="mi">67</span> <span class="mi">68</span> <span class="mi">65</span><span class="p">]</span>
<span class="p">[</span><span class="mi">56</span> <span class="mi">67</span> <span class="mi">49</span> <span class="mi">61</span> <span class="mi">18</span> <span class="mi">34</span> <span class="mi">53</span> <span class="mi">21</span> <span class="mi">7</span> <span class="mi">48</span> <span class="mi">32</span><span class="p">]</span>
<span class="p">[</span><span class="mi">15</span> <span class="mi">70</span> <span class="mi">10</span> <span class="mi">34</span> <span class="mi">1</span> <span class="mi">57</span> <span class="mi">70</span> <span class="mi">27</span> <span class="mi">12</span> <span class="mi">33</span> <span class="mi">46</span><span class="p">]</span>
<span class="p">[</span><span class="mi">25</span> <span class="mi">29</span> <span class="mi">20</span> <span class="mi">21</span> <span class="mi">30</span> <span class="mi">55</span> <span class="mi">63</span> <span class="mi">49</span> <span class="mi">11</span> <span class="mi">36</span> <span class="mi">7</span><span class="p">]</span>
<span class="n">L</span> <span class="o">*</span> <span class="n">U</span> <span class="o">*</span> <span class="n">L</span> <span class="o">=</span>
<span class="p">[</span><span class="mi">50</span> <span class="mi">8</span> <span class="mi">21</span> <span class="mi">16</span> <span class="mi">13</span> <span class="mi">33</span> <span class="mi">2</span> <span class="mi">12</span> <span class="mi">35</span> <span class="mi">20</span> <span class="mi">14</span><span class="p">]</span>
<span class="p">[</span><span class="mi">36</span> <span class="mi">55</span> <span class="mi">36</span> <span class="mi">34</span> <span class="mi">27</span> <span class="mi">28</span> <span class="mi">23</span> <span class="mi">21</span> <span class="mi">62</span> <span class="mi">17</span> <span class="mi">8</span><span class="p">]</span>
<span class="p">[</span><span class="mi">56</span> <span class="mi">26</span> <span class="mi">49</span> <span class="mi">39</span> <span class="mi">43</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">46</span> <span class="mi">0</span> <span class="mi">58</span> <span class="mi">43</span><span class="p">]</span>
<span class="p">[</span><span class="mi">11</span> <span class="mi">25</span> <span class="mi">25</span> <span class="mi">35</span> <span class="mi">29</span> <span class="mi">0</span> <span class="mi">22</span> <span class="mi">38</span> <span class="mi">53</span> <span class="mi">51</span> <span class="mi">58</span><span class="p">]</span>
<span class="p">[</span><span class="mi">34</span> <span class="mi">14</span> <span class="mi">69</span> <span class="mi">68</span> <span class="mi">5</span> <span class="mi">32</span> <span class="mi">27</span> <span class="mi">4</span> <span class="mi">27</span> <span class="mi">62</span> <span class="mi">15</span><span class="p">]</span>
<span class="p">[</span><span class="mi">46</span> <span class="mi">49</span> <span class="mi">36</span> <span class="mi">42</span> <span class="mi">26</span> <span class="mi">12</span> <span class="mi">28</span> <span class="mi">60</span> <span class="mi">54</span> <span class="mi">66</span> <span class="mi">23</span><span class="p">]</span>
<span class="p">[</span><span class="mi">69</span> <span class="mi">55</span> <span class="mi">30</span> <span class="mi">65</span> <span class="mi">56</span> <span class="mi">13</span> <span class="mi">14</span> <span class="mi">36</span> <span class="mi">26</span> <span class="mi">46</span> <span class="mi">48</span><span class="p">]</span>
<span class="p">[</span><span class="mi">25</span> <span class="mi">48</span> <span class="mi">16</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">57</span> <span class="mi">64</span> <span class="mi">62</span> <span class="mi">61</span> <span class="mi">25</span> <span class="mi">62</span><span class="p">]</span>
<span class="p">[</span><span class="mi">68</span> <span class="mi">39</span> <span class="mi">11</span> <span class="mi">40</span> <span class="mi">25</span> <span class="mi">11</span> <span class="mi">7</span> <span class="mi">40</span> <span class="mi">24</span> <span class="mi">43</span> <span class="mi">65</span><span class="p">]</span>
<span class="p">[</span><span class="mi">54</span> <span class="mi">20</span> <span class="mi">40</span> <span class="mi">59</span> <span class="mi">52</span> <span class="mi">60</span> <span class="mi">37</span> <span class="mi">14</span> <span class="mi">32</span> <span class="mi">44</span> <span class="mi">4</span><span class="p">]</span>
<span class="p">[</span><span class="mi">45</span> <span class="mi">20</span> <span class="mi">7</span> <span class="mi">26</span> <span class="mi">45</span> <span class="mi">45</span> <span class="mi">50</span> <span class="mi">17</span> <span class="mi">41</span> <span class="mi">59</span> <span class="mi">50</span><span class="p">]</span>
<span class="n">L</span><span class="o">^</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">S</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="n">L</span> <span class="o">=</span>
<span class="p">[</span><span class="mi">34</span> <span class="mi">12</span> <span class="mi">70</span> <span class="mi">21</span> <span class="mi">36</span> <span class="mi">2</span> <span class="mi">2</span> <span class="mi">43</span> <span class="mi">7</span> <span class="mi">14</span> <span class="mi">2</span><span class="p">]</span>
<span class="p">[</span> <span class="mi">1</span> <span class="mi">54</span> <span class="mi">59</span> <span class="mi">12</span> <span class="mi">64</span> <span class="mi">35</span> <span class="mi">9</span> <span class="mi">7</span> <span class="mi">49</span> <span class="mi">11</span> <span class="mi">49</span><span class="p">]</span>
<span class="p">[</span><span class="mi">69</span> <span class="mi">14</span> <span class="mi">10</span> <span class="mi">19</span> <span class="mi">16</span> <span class="mi">27</span> <span class="mi">11</span> <span class="mi">9</span> <span class="mi">26</span> <span class="mi">10</span> <span class="mi">45</span><span class="p">]</span>
<span class="p">[</span><span class="mi">70</span> <span class="mi">17</span> <span class="mi">41</span> <span class="mi">13</span> <span class="mi">35</span> <span class="mi">58</span> <span class="mi">19</span> <span class="mi">29</span> <span class="mi">70</span> <span class="mi">5</span> <span class="mi">30</span><span class="p">]</span>
<span class="p">[</span><span class="mi">68</span> <span class="mi">69</span> <span class="mi">67</span> <span class="mi">37</span> <span class="mi">63</span> <span class="mi">69</span> <span class="mi">15</span> <span class="mi">64</span> <span class="mi">66</span> <span class="mi">28</span> <span class="mi">26</span><span class="p">]</span>
<span class="p">[</span><span class="mi">18</span> <span class="mi">29</span> <span class="mi">64</span> <span class="mi">38</span> <span class="mi">63</span> <span class="mi">67</span> <span class="mi">15</span> <span class="mi">27</span> <span class="mi">64</span> <span class="mi">6</span> <span class="mi">26</span><span class="p">]</span>
<span class="p">[</span> <span class="mi">0</span> <span class="mi">12</span> <span class="mi">40</span> <span class="mi">41</span> <span class="mi">48</span> <span class="mi">30</span> <span class="mi">46</span> <span class="mi">52</span> <span class="mi">39</span> <span class="mi">48</span> <span class="mi">58</span><span class="p">]</span>
<span class="p">[</span><span class="mi">22</span> <span class="mi">3</span> <span class="mi">28</span> <span class="mi">35</span> <span class="mi">55</span> <span class="mi">30</span> <span class="mi">15</span> <span class="mi">17</span> <span class="mi">22</span> <span class="mi">49</span> <span class="mi">55</span><span class="p">]</span>
<span class="p">[</span><span class="mi">50</span> <span class="mi">55</span> <span class="mi">55</span> <span class="mi">61</span> <span class="mi">45</span> <span class="mi">23</span> <span class="mi">24</span> <span class="mi">32</span> <span class="mi">10</span> <span class="mi">59</span> <span class="mi">69</span><span class="p">]</span>
<span class="p">[</span><span class="mi">27</span> <span class="mi">21</span> <span class="mi">68</span> <span class="mi">56</span> <span class="mi">67</span> <span class="mi">49</span> <span class="mi">64</span> <span class="mi">53</span> <span class="mi">42</span> <span class="mi">46</span> <span class="mi">14</span><span class="p">]</span>
<span class="p">[</span><span class="mi">42</span> <span class="mi">66</span> <span class="mi">16</span> <span class="mi">29</span> <span class="mi">42</span> <span class="mi">42</span> <span class="mi">23</span> <span class="mi">49</span> <span class="mi">43</span> <span class="mi">3</span> <span class="mi">23</span><span class="p">]</span>
<span class="n">R</span><span class="o">^</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">S</span><span class="o">^</span><span class="mi">8</span> <span class="o">=</span>
<span class="p">[</span><span class="mi">51</span> <span class="mi">9</span> <span class="mi">22</span> <span class="mi">61</span> <span class="mi">63</span> <span class="mi">14</span> <span class="mi">2</span> <span class="mi">4</span> <span class="mi">18</span> <span class="mi">18</span> <span class="mi">23</span><span class="p">]</span>
<span class="p">[</span><span class="mi">33</span> <span class="mi">53</span> <span class="mi">31</span> <span class="mi">31</span> <span class="mi">62</span> <span class="mi">21</span> <span class="mi">66</span> <span class="mi">7</span> <span class="mi">66</span> <span class="mi">68</span> <span class="mi">7</span><span class="p">]</span>
<span class="p">[</span><span class="mi">59</span> <span class="mi">19</span> <span class="mi">32</span> <span class="mi">21</span> <span class="mi">13</span> <span class="mi">34</span> <span class="mi">16</span> <span class="mi">43</span> <span class="mi">49</span> <span class="mi">25</span> <span class="mi">7</span><span class="p">]</span>
<span class="p">[</span><span class="mi">44</span> <span class="mi">37</span> <span class="mi">4</span> <span class="mi">29</span> <span class="mi">70</span> <span class="mi">50</span> <span class="mi">46</span> <span class="mi">39</span> <span class="mi">55</span> <span class="mi">4</span> <span class="mi">65</span><span class="p">]</span>
<span class="p">[</span><span class="mi">29</span> <span class="mi">63</span> <span class="mi">29</span> <span class="mi">43</span> <span class="mi">47</span> <span class="mi">28</span> <span class="mi">40</span> <span class="mi">33</span> <span class="mi">0</span> <span class="mi">62</span> <span class="mi">8</span><span class="p">]</span>
<span class="p">[</span><span class="mi">45</span> <span class="mi">62</span> <span class="mi">36</span> <span class="mi">68</span> <span class="mi">10</span> <span class="mi">66</span> <span class="mi">26</span> <span class="mi">48</span> <span class="mi">10</span> <span class="mi">6</span> <span class="mi">61</span><span class="p">]</span>
<span class="p">[</span><span class="mi">43</span> <span class="mi">30</span> <span class="mi">25</span> <span class="mi">18</span> <span class="mi">23</span> <span class="mi">38</span> <span class="mi">61</span> <span class="mi">0</span> <span class="mi">52</span> <span class="mi">46</span> <span class="mi">35</span><span class="p">]</span>
<span class="p">[</span> <span class="mi">3</span> <span class="mi">40</span> <span class="mi">6</span> <span class="mi">45</span> <span class="mi">20</span> <span class="mi">55</span> <span class="mi">35</span> <span class="mi">67</span> <span class="mi">25</span> <span class="mi">14</span> <span class="mi">63</span><span class="p">]</span>
<span class="p">[</span><span class="mi">15</span> <span class="mi">30</span> <span class="mi">61</span> <span class="mi">66</span> <span class="mi">25</span> <span class="mi">33</span> <span class="mi">14</span> <span class="mi">20</span> <span class="mi">60</span> <span class="mi">50</span> <span class="mi">50</span><span class="p">]</span>
<span class="p">[</span><span class="mi">29</span> <span class="mi">15</span> <span class="mi">53</span> <span class="mi">22</span> <span class="mi">55</span> <span class="mi">64</span> <span class="mi">69</span> <span class="mi">56</span> <span class="mi">44</span> <span class="mi">40</span> <span class="mi">8</span><span class="p">]</span>
<span class="p">[</span><span class="mi">28</span> <span class="mi">40</span> <span class="mi">69</span> <span class="mi">60</span> <span class="mi">28</span> <span class="mi">41</span> <span class="mi">9</span> <span class="mi">14</span> <span class="mi">29</span> <span class="mi">4</span> <span class="mi">29</span><span class="p">]</span>
</code></pre></div></div>
<h3 id="solution-1">Solution</h3>
<p>In this challenge, we are given the source code of an encryption scheme that uses matrix operations for encryption and decryption, the corresponding encrypted flag and some hints.</p>
<p>For the encryption part:</p>
\[E = L^{-1}Y = L^{-1}SX = L^{-1}LU(A+R) = U(A+R)\]
<p>The three hints we have is $LUL$, $L^{-1}S^2L$ and $R^{-1}S^8$</p>
<p>Since $S=LU$, we can rewrite the second hint as $ULUL$, then we can get $U$ by dividing hint1.
For the third hint $R^{-1}S^8$, we can rewrite it as $R^{-1}(LULU)^4=R^{-1}(h_1U)^4$, then we can get $R$.</p>
<p>With $U$ and $R$ known, we can then recover the flag $A$ from $E$.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">Matrix</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="mi">71</span><span class="p">),[[</span><span class="mi">25</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">19</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">37</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">21</span><span class="p">],</span>
<span class="p">[</span><span class="mi">20</span><span class="p">,</span><span class="mi">57</span><span class="p">,</span><span class="mi">39</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">37</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="mi">31</span><span class="p">,</span><span class="mi">70</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">47</span><span class="p">],</span>
<span class="p">[</span><span class="mi">56</span><span class="p">,</span><span class="mi">31</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">67</span><span class="p">,</span><span class="mi">38</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">14</span><span class="p">],</span>
<span class="p">[</span><span class="mi">42</span><span class="p">,</span><span class="mi">54</span><span class="p">,</span><span class="mi">38</span><span class="p">,</span><span class="mi">22</span><span class="p">,</span><span class="mi">19</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="mi">45</span><span class="p">,</span><span class="mi">53</span><span class="p">,</span><span class="mi">39</span><span class="p">],</span>
<span class="p">[</span><span class="mi">55</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">60</span><span class="p">,</span><span class="mi">64</span><span class="p">],</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">38</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">19</span><span class="p">,</span><span class="mi">57</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">14</span><span class="p">],</span>
<span class="p">[</span><span class="mi">13</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">38</span><span class="p">,</span><span class="mi">54</span><span class="p">,</span><span class="mi">23</span><span class="p">,</span><span class="mi">34</span><span class="p">,</span><span class="mi">54</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">56</span><span class="p">,</span><span class="mi">29</span><span class="p">],</span>
<span class="p">[</span><span class="mi">26</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">70</span><span class="p">,</span><span class="mi">44</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">67</span><span class="p">,</span><span class="mi">68</span><span class="p">,</span><span class="mi">65</span><span class="p">],</span>
<span class="p">[</span><span class="mi">56</span><span class="p">,</span><span class="mi">67</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="mi">34</span><span class="p">,</span><span class="mi">53</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">32</span><span class="p">],</span>
<span class="p">[</span><span class="mi">15</span><span class="p">,</span><span class="mi">70</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">34</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">57</span><span class="p">,</span><span class="mi">70</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">12</span><span class="p">,</span><span class="mi">33</span><span class="p">,</span><span class="mi">46</span><span class="p">],</span>
<span class="p">[</span><span class="mi">25</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">36</span><span class="p">,</span><span class="mi">7</span><span class="p">]])</span>
<span class="n">hint1</span> <span class="o">=</span> <span class="n">Matrix</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="mi">71</span><span class="p">),[[</span><span class="mi">50</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">13</span><span class="p">,</span><span class="mi">33</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">12</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">14</span><span class="p">],</span>
<span class="p">[</span><span class="mi">36</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">36</span><span class="p">,</span><span class="mi">34</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">23</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">62</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">8</span><span class="p">],</span>
<span class="p">[</span><span class="mi">56</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">39</span><span class="p">,</span><span class="mi">43</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">58</span><span class="p">,</span><span class="mi">43</span><span class="p">],</span>
<span class="p">[</span><span class="mi">11</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">22</span><span class="p">,</span><span class="mi">38</span><span class="p">,</span><span class="mi">53</span><span class="p">,</span><span class="mi">51</span><span class="p">,</span><span class="mi">58</span><span class="p">],</span>
<span class="p">[</span><span class="mi">34</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">69</span><span class="p">,</span><span class="mi">68</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">32</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">62</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span>
<span class="p">[</span><span class="mi">46</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">36</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">12</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">60</span><span class="p">,</span><span class="mi">54</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">23</span><span class="p">],</span>
<span class="p">[</span><span class="mi">69</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">65</span><span class="p">,</span><span class="mi">56</span><span class="p">,</span><span class="mi">13</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">36</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">48</span><span class="p">],</span>
<span class="p">[</span><span class="mi">25</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">34</span><span class="p">,</span><span class="mi">57</span><span class="p">,</span><span class="mi">64</span><span class="p">,</span><span class="mi">62</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">62</span><span class="p">],</span>
<span class="p">[</span><span class="mi">68</span><span class="p">,</span><span class="mi">39</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="mi">43</span><span class="p">,</span><span class="mi">65</span><span class="p">],</span>
<span class="p">[</span><span class="mi">54</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">59</span><span class="p">,</span><span class="mi">52</span><span class="p">,</span><span class="mi">60</span><span class="p">,</span><span class="mi">37</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">32</span><span class="p">,</span><span class="mi">44</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span>
<span class="p">[</span><span class="mi">45</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">45</span><span class="p">,</span><span class="mi">45</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">41</span><span class="p">,</span><span class="mi">59</span><span class="p">,</span><span class="mi">50</span><span class="p">]])</span>
<span class="n">hint2</span><span class="o">=</span><span class="n">Matrix</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="mi">71</span><span class="p">),[[</span><span class="mi">34</span><span class="p">,</span><span class="mi">12</span><span class="p">,</span><span class="mi">70</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">36</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">43</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">54</span><span class="p">,</span><span class="mi">59</span><span class="p">,</span><span class="mi">12</span><span class="p">,</span><span class="mi">64</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">49</span><span class="p">],</span>
<span class="p">[</span><span class="mi">69</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">19</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">45</span><span class="p">],</span>
<span class="p">[</span><span class="mi">70</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">41</span><span class="p">,</span><span class="mi">13</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">58</span><span class="p">,</span><span class="mi">19</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">70</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">30</span><span class="p">],</span>
<span class="p">[</span><span class="mi">68</span><span class="p">,</span><span class="mi">69</span><span class="p">,</span><span class="mi">67</span><span class="p">,</span><span class="mi">37</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="mi">69</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">64</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">26</span><span class="p">],</span>
<span class="p">[</span><span class="mi">18</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">64</span><span class="p">,</span><span class="mi">38</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="mi">67</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">64</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">26</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">12</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">41</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">52</span><span class="p">,</span><span class="mi">39</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">58</span><span class="p">],</span>
<span class="p">[</span><span class="mi">22</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">22</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">55</span><span class="p">],</span>
<span class="p">[</span><span class="mi">50</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">45</span><span class="p">,</span><span class="mi">23</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="mi">32</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">59</span><span class="p">,</span><span class="mi">69</span><span class="p">],</span>
<span class="p">[</span><span class="mi">27</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">68</span><span class="p">,</span><span class="mi">56</span><span class="p">,</span><span class="mi">67</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">64</span><span class="p">,</span><span class="mi">53</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">14</span><span class="p">],</span>
<span class="p">[</span><span class="mi">42</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">23</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">43</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">23</span><span class="p">]])</span>
<span class="n">hint3</span><span class="o">=</span><span class="n">Matrix</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="mi">71</span><span class="p">),[[</span><span class="mi">51</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">22</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="mi">23</span><span class="p">],</span>
<span class="p">[</span><span class="mi">33</span><span class="p">,</span><span class="mi">53</span><span class="p">,</span><span class="mi">31</span><span class="p">,</span><span class="mi">31</span><span class="p">,</span><span class="mi">62</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">68</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span>
<span class="p">[</span><span class="mi">59</span><span class="p">,</span><span class="mi">19</span><span class="p">,</span><span class="mi">32</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">13</span><span class="p">,</span><span class="mi">34</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">43</span><span class="p">,</span><span class="mi">49</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">7</span><span class="p">],</span>
<span class="p">[</span><span class="mi">44</span><span class="p">,</span><span class="mi">37</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">70</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">39</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">65</span><span class="p">],</span>
<span class="p">[</span><span class="mi">29</span><span class="p">,</span><span class="mi">63</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">43</span><span class="p">,</span><span class="mi">47</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">33</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">62</span><span class="p">,</span><span class="mi">8</span><span class="p">],</span>
<span class="p">[</span><span class="mi">45</span><span class="p">,</span><span class="mi">62</span><span class="p">,</span><span class="mi">36</span><span class="p">,</span><span class="mi">68</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">48</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">61</span><span class="p">],</span>
<span class="p">[</span><span class="mi">43</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="mi">23</span><span class="p">,</span><span class="mi">38</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">52</span><span class="p">,</span><span class="mi">46</span><span class="p">,</span><span class="mi">35</span><span class="p">],</span>
<span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">45</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">35</span><span class="p">,</span><span class="mi">67</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">63</span><span class="p">],</span>
<span class="p">[</span><span class="mi">15</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">33</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">60</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">50</span><span class="p">],</span>
<span class="p">[</span><span class="mi">29</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">53</span><span class="p">,</span><span class="mi">22</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">64</span><span class="p">,</span><span class="mi">69</span><span class="p">,</span><span class="mi">56</span><span class="p">,</span><span class="mi">44</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">8</span><span class="p">],</span>
<span class="p">[</span><span class="mi">28</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">69</span><span class="p">,</span><span class="mi">60</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">41</span><span class="p">,</span><span class="mi">9</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">29</span><span class="p">]])</span>
<span class="n">U</span> <span class="o">=</span> <span class="n">hint2</span><span class="o">/</span><span class="n">hint1</span>
<span class="n">R</span> <span class="o">=</span> <span class="p">(</span><span class="n">hint3</span><span class="o">/</span><span class="n">U</span><span class="o">/</span><span class="n">hint1</span><span class="o">/</span><span class="n">U</span><span class="o">/</span><span class="n">hint1</span><span class="o">/</span><span class="n">U</span><span class="o">/</span><span class="n">hint1</span><span class="o">/</span><span class="n">U</span><span class="o">/</span><span class="n">hint1</span><span class="p">).</span><span class="n">inverse</span><span class="p">()</span>
<span class="n">A</span> <span class="o">=</span> <span class="n">U</span><span class="p">.</span><span class="n">inverse</span><span class="p">()</span><span class="o">*</span><span class="n">E</span><span class="o">-</span><span class="n">R</span>
<span class="n">alphabet</span> <span class="o">=</span> <span class="s">'=0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$!?_{}<>'</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">24</span><span class="p">):</span>
<span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">5</span><span class="o">*</span><span class="n">k</span> <span class="o">//</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">5</span><span class="o">*</span><span class="n">k</span> <span class="o">%</span> <span class="mi">11</span>
<span class="n">flag</span><span class="o">+=</span><span class="n">alphabet</span><span class="p">[</span><span class="n">A</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]]</span>
<span class="k">print</span><span class="p">(</span><span class="s">'CCTF{'</span><span class="o">+</span><span class="n">flag</span><span class="o">+</span><span class="s">'}'</span><span class="p">)</span>
</code></pre></div></div>
<h5 id="flag-1">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{LU__D3c0mpO517Ion__4L90?}</code></p>
<h2 id="improved">Improved</h2>
<blockquote>
<p>Coming Soon</p>
</blockquote>
<h2 id="maid">Maid</h2>
<h3 id="challenge-2">Challenge</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">gmpy2</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">global</span> <span class="n">nbit</span>
<span class="n">nbit</span> <span class="o">=</span> <span class="mi">1024</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">(</span><span class="n">nbit</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="p">[</span><span class="n">getStrongPrime</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="s">'01'</span><span class="p">]</span>
<span class="k">if</span> <span class="n">p</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="n">q</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="k">return</span> <span class="p">(</span><span class="n">p</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span><span class="o">*</span><span class="n">q</span><span class="p">,</span> <span class="n">p</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">):</span>
<span class="k">if</span> <span class="n">GCD</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">m</span> <span class="o">>=</span> <span class="mi">2</span><span class="o">**</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">nbit</span> <span class="o">-</span> <span class="mi">2</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">None</span>
<span class="k">return</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">flag_encrypt</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">):</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">m</span> <span class="o"><</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="k">return</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="mi">65537</span><span class="p">,</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" hi all, welcome to Rooney Oracle, you can encrypt and decrypt any "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" message in this oracle, but the flag is still encrypted, Rooney "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" asked me to find the encrypted flag, I'm trying now, please help! "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pubkey</span><span class="p">,</span> <span class="n">privkey</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">privkey</span><span class="p">,</span> <span class="n">pubkey</span> <span class="o">//</span> <span class="p">(</span><span class="n">privkey</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[E]ncrypt message </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[D]ecrypt ciphertext </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[S]how encrypted flag </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'e'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Send the message to encrypt: "</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">msg</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your message is not integer!!"</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">"| encrypt(msg, pubkey) = </span><span class="si">{</span><span class="n">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">)</span><span class="si">}</span><span class="s"> "</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'d'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Send the ciphertext to decrypt: "</span><span class="p">)</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">enc</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">enc</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your message is not integer!!"</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">"| decrypt(enc, privkey) = </span><span class="si">{</span><span class="n">decrypt</span><span class="p">(</span><span class="n">enc</span><span class="p">,</span> <span class="n">privkey</span><span class="p">)</span><span class="si">}</span><span class="s"> "</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'s'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| enc = </span><span class="si">{</span><span class="n">flag_encrypt</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<p>We are given access to an oracle which allows us to encrypt and decrypt data with</p>
\[c = m^2 \pmod n, \qquad n = p^2 q\]
<p>and we can request a flag encrypted as</p>
\[c = m^{e} \pmod {pq}, \qquad e = 65537\]
<p>Where $p,q$ are 1024 bit primes. The goal is to use the oracle to factor $n$ and hence obtain the flag.</p>
<h3 id="solution-2">Solution</h3>
<p>The first step is to obtain $n = p^2 q$, which we can do by computing:</p>
\[n = \gcd(m_1^2 - c_1, m^2_2 - c_2)\]
<p>by using the oracle to obtain $c_i$ from integers $m_i$.</p>
<p>Note: there may by other factors, and we actually compute $kn$ for some $k \in \mathbb{Z}$. We can ensure $k = 1$ by computing many $m_i,c_i$ and taking the gcd many times.</p>
<p>The second step is to obtain one of the prime factors.</p>
<p>We cannot send very large numbers to encrypt, but can get around this by sending $E(-X)$ for arbitary sized $X$. As the encryption is simply squaring, this makes no difference. <strong>Defund</strong> noticed that if you decrypt $X = D(2)$ and then compute $E(-X)$, you do not obtain $2$, but rather some very large integer.</p>
<p>I’m not sure how <strong>Defund</strong> solved it, but playing with the numbers while writing it up, I noticed that:</p>
\[\gcd(n, D(-1) - 1) = p\]
<p>which allowed me to solve. Looking around online, some other people seem to have solved by doing something like</p>
\[\gcd(n, D(m)^2 - m ) = p^2\]
<p>but seeing as we have no source, a bit of guess work needed to be done one way or another, which seems like a shame.</p>
<h4 id="implementation">Implementation</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'04.cr.yp.toc.tf'</span><span class="p">,</span> <span class="mi">38010</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"[Q]uit"</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">"E"</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"encrypt: "</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">))</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"[Q]uit"</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">"D"</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"decrypt: "</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">))</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">get_flag</span><span class="p">():</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"[Q]uit"</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">"S"</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">" = "</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">strip</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">recover_n</span><span class="p">():</span>
<span class="c1"># Obtain kn
</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">2</span><span class="o">**</span><span class="mi">1536</span> <span class="o">-</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="o">**</span><span class="mi">1000</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">m</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">c</span>
<span class="c1"># Remove all factors of two
</span> <span class="k">while</span> <span class="n">n</span><span class="o">%</span><span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="mi">2</span>
<span class="c1"># Compute a few more GCD to remove any other factors.
</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">m</span> <span class="o">=</span> <span class="mi">2</span><span class="o">**</span><span class="mi">1536</span> <span class="o">-</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="o">**</span><span class="mi">1000</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">gcd</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">c</span><span class="p">)</span>
<span class="k">return</span> <span class="n">n</span>
<span class="k">def</span> <span class="nf">dec_flag</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="n">q</span><span class="p">):</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">get_flag</span><span class="p">()</span>
<span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mh">0x10001</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">m</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">p</span><span class="o">*</span><span class="n">q</span><span class="p">)</span>
<span class="k">return</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">recover_factors</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">X</span> <span class="o">=</span> <span class="n">decrypt</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">gcd</span><span class="p">(</span><span class="n">X</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="p">(</span><span class="n">p</span><span class="o">*</span><span class="n">p</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
<span class="k">return</span> <span class="n">p</span><span class="p">,</span> <span class="n">q</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">recover_n</span><span class="p">()</span>
<span class="n">p</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">recover_factors</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">dec_flag</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="n">q</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="c1"># CCTF{___Ra8!N_H_Cryp70_5YsT3M___}
</span></code></pre></div></div>
<h5 id="flag-2">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{___Ra8!N_H_Cryp70_5YsT3M___}</code></p>
<h3 id="decryption">Decryption</h3>
<p>At the end of the CTF, Factoreal shared the decrypt function. Seeing this, the methods of solving make sense, but it seems like a shame that this wasn’t included within the challenge</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">decrypt</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">privkey</span><span class="p">):</span>
<span class="n">m_p</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="p">(</span><span class="n">privkey</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="mi">4</span><span class="p">,</span> <span class="n">privkey</span><span class="p">)</span>
<span class="n">i</span> <span class="o">=</span> <span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m_p</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span> <span class="o">//</span> <span class="n">privkey</span>
<span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">m_p</span><span class="p">,</span> <span class="n">privkey</span><span class="p">)</span> <span class="o">%</span> <span class="n">privkey</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">m_p</span> <span class="o">+</span> <span class="n">j</span> <span class="o">*</span> <span class="n">privkey</span>
<span class="k">if</span> <span class="mi">2</span><span class="o">*</span><span class="n">m</span> <span class="o"><</span> <span class="n">privkey</span><span class="o">**</span><span class="mi">2</span><span class="p">:</span>
<span class="k">return</span> <span class="n">m</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">privkey</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">m</span>
</code></pre></div></div>
<h2 id="wolf">Wolf</h2>
<h3 id="challenge-3">Challenge</h3>
<p>When we connect to the server, it chooses a random length <code class="language-plaintext highlighter-rouge">niv</code>
between 1 and 11, and a random nonce of that length. We can request
the flag encrypted using AES-GCM with the key <code class="language-plaintext highlighter-rouge">HungryTimberWolf</code> and
that IV, and ask for the server to encrypt our input with the same
parameters.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Cryptodome.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">import</span> <span class="nn">os</span><span class="p">,</span> <span class="n">time</span><span class="p">,</span> <span class="n">sys</span><span class="p">,</span> <span class="n">random</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="n">passphrase</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'HungryTimberWolf'</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">passphrase</span><span class="p">,</span> <span class="n">niv</span><span class="p">):</span>
<span class="n">msg_header</span> <span class="o">=</span> <span class="s">'EPOCH:'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()))</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">msg_header</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span> <span class="o">+</span> <span class="n">msg</span> <span class="o">+</span> <span class="s">'='</span> <span class="o">*</span> <span class="p">(</span><span class="mi">15</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">aes</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">passphrase</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_GCM</span><span class="p">,</span> <span class="n">nonce</span> <span class="o">=</span> <span class="n">niv</span><span class="p">)</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">aes</span><span class="p">.</span><span class="n">encrypt_and_digest</span><span class="p">(</span><span class="n">msg</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="n">enc</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" hi wolf hunters, welcome to the most dangerous hunting ground!! "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" decrypt the encrypted message and get the flag as a nice prize! "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">niv</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">urandom</span><span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">11</span><span class="p">))</span>
<span class="n">flag_enc</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">passphrase</span><span class="p">,</span> <span class="n">niv</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[G]et the encrypted flag </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[T]est the encryption </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'g'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| encrypt(flag) = </span><span class="si">{</span><span class="n">flag_enc</span><span class="p">.</span><span class="nb">hex</span><span class="p">()</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'t'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Please send your message to encrypt: "</span><span class="p">)</span>
<span class="n">msg_inp</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">msg_inp</span><span class="p">,</span> <span class="n">passphrase</span><span class="p">,</span> <span class="n">niv</span><span class="p">).</span><span class="nb">hex</span><span class="p">()</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| enc = </span><span class="si">{</span><span class="n">enc</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<h3 id="solution-3">Solution</h3>
<p>Since <code class="language-plaintext highlighter-rouge">niv</code> is uniformly random, in one out of 11 connections the nonce will only be one byte long. If this happens, we can easily bruteforce the encrypted flag: we already know the key, and can try all 256 nonce values to see if one of them gives a plaintext that looks like a flag.</p>
<p>A quick Python script collects encrypted flags, which we can dump into a single file to process later:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#! /usr/bin/env python
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">serv</span> <span class="o">=</span> <span class="n">pwnlib</span><span class="p">.</span><span class="n">tubes</span><span class="p">.</span><span class="n">remote</span><span class="p">.</span><span class="n">remote</span><span class="p">(</span><span class="s">'01.cr.yp.toc.tf'</span><span class="p">,</span> <span class="mi">27010</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'g'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'q'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">serv</span><span class="p">.</span><span class="n">recvall</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">):</span>
<span class="k">if</span> <span class="s">'encrypt(flag)'</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">line</span><span class="p">.</span><span class="n">rstrip</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>
<p>The solver isn’t much longer:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#! /usr/bin/env python
</span><span class="kn">from</span> <span class="nn">Cryptodome.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">import</span> <span class="nn">binascii</span>
<span class="k">def</span> <span class="nf">trysolve</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
<span class="k">for</span> <span class="n">iv</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">256</span><span class="p">):</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="sa">b</span><span class="s">'HungryTimberWolf'</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_GCM</span><span class="p">,</span> <span class="n">nonce</span><span class="o">=</span><span class="nb">bytes</span><span class="p">([</span><span class="n">iv</span><span class="p">]))</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">binascii</span><span class="p">.</span><span class="n">unhexlify</span><span class="p">(</span><span class="n">line</span><span class="p">))</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">'CTF'</span> <span class="ow">in</span> <span class="n">flag</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'flags.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">f</span><span class="p">.</span><span class="n">readlines</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'['</span><span class="p">):</span>
<span class="n">trysolve</span><span class="p">(</span><span class="n">line</span><span class="p">.</span><span class="n">rstrip</span><span class="p">())</span>
</code></pre></div></div>
<h5 id="flag-3">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{____w0lveS____c4n____be____dan9er0uS____t0____p3oplE____!!!!!!}</code></p>
<h2 id="ferman">Ferman</h2>
<h3 id="challenge-4">Challenge</h3>
<blockquote>
<p>Modern cryptographic algorithms are the theoretical foundations and the core technologies of information security. Should we emphasize more?</p>
<p><code class="language-plaintext highlighter-rouge">nc 07.cr.yp.toc.tf 22010</code></p>
</blockquote>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ hi talented participants, welcome to the FERMAN cryptography task! +
+ Solve the given equations and decrypt the encrypted flag! Enjoy! +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| Parameters generation is a bit time consuming, so please be patient :P
| Options:
| [P]rint encrypted flag
| [R]eveal the parameters
| [Q]uit
P
| encrypt(flag) = 6489656589950752810044571176882070993656025408411955877914111875896024399252967804237101085443293019406006339555779534657926807551928549712558667515175079267695028070934727514846970003337126120540450206565849474378607706030211234939933160392491902242074123763448231072583065175864490510115483208842110529309232348180718641618424365058379284549574700049803925884878710773408472100779358561980206902500388524570616750475958017638946408491011264747032498524679282489181606124604218147
R
e = 65537
isPrime(p) = True
isPrime(q) = True
n = p * q
(p - 127)**2 + (q - 184)**2 = 13809252727788824044233595548226590341967726502046327883413398709726819135921363848617960542444505497356040393690402758557636039683075007984614264314802550433942617885990971202110511768121760826488944622697964930982921462840320850014092598270493079542993367042001339267321218767132063176291998391714014192946596879176425904447127657664796094937171819714510504836456988487840790317576922986001688147359646287894578550322731904860694734616037751755921771706899493873123836562784063321
m = bytes_to_long(flag)
c = pow(m, e, n)
</code></pre></div></div>
<h3 id="solution-4">Solution</h3>
<p>On each connection, we are given a flag encrypted using RSA, with additional information in the form</p>
\[(p - a)^2 + (q - b)^2 = w\]
<p>On every connection, the integers $a,b,w$ are different, although $a,b$ are usually small ($a,b < 2000$ ).</p>
<p><strong>Lyutoon</strong> and <strong>Ratman</strong> noticed that factoring $z$, it was always a seventh power $w = z^t$, which means we can write the equation as:</p>
\[x^2 + y^2 = z^7\]
<p>We can factor the left hand side by writing:</p>
\[x^2 + y^2 = (x + iy)(x - iy)\]
<p>and now we realise that by factoring $z^7$ as a Gaussian integer in $\mathbb{Z}[i]$:</p>
\[z = \prod_i (a_i + i b_i)\]
<p>we can obtain $x,y$, as $(x + i y)$ will be a divisor of $z \in \mathbb{Z}[i]$, and from this solve for $p,q$ to grab the flag.</p>
<p>Connecting again, we get:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="mi">2265</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">902</span>
<span class="n">w</span> <span class="o">=</span> <span class="mi">24007015341450638047707811509679207068051724063799752621201994109462561550079479155110637624506028551099549192036601169213196430196182069103932872524092047760624845002308713558682251660517182097667675473038586407097498167776645896369165963981698265040400341878755056463554861788991872633206414266159558715922583613630387512303492920597052611976890648632123534922756985895479931541478630417251021677032459939450624439421018438357005854556082128718286537575550378203702362524442461229</span>
<span class="n">flag_enc</span> <span class="o">=</span> <span class="mi">10564879569008106132040759805988959471544940722100428235462653367215001622634768902220485764070394703676633460036566842009467954832811287152142597331508344786167188766356935684044757086902094847810694941751879500776345600036096556068243767090470376672110936445246103465175956767665996275085293250901512809704594905257754009538501795362031873203086994610168776981264025121998840163864902563628991590207637487738286741829585819040077197755226202284847</span>
</code></pre></div></div>
<p>Obtaining the factors of $z \in \mathbb{Z}[i]$ we find:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="mi">2265</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">902</span>
<span class="n">z</span> <span class="o">=</span> <span class="n">w</span><span class="o">^</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">7</span><span class="p">)</span>
<span class="n">K</span> <span class="o">=</span> <span class="n">ZZ</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="n">gaussian_factors</span> <span class="o">=</span> <span class="n">factor</span><span class="p">(</span><span class="n">K</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
<span class="c1"># gaussian_factors (-I) * (-1236649975237776943493190425869173*I - 3575914522629734831030006136433790) * (-5*I - 4) * (4*I + 5) * (-1236649975237776943493190425869173*I + 3575914522629734831030006136433790)
</span></code></pre></div></div>
<p>We now know that $(x + iy)$ is some divisor of $z$, and knowing that $p,q$ are prime, we can find these easily</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">z_test</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">1236649975237776943493190425869173</span><span class="o">*</span><span class="n">I</span> <span class="o">-</span> <span class="mi">3575914522629734831030006136433790</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="mi">4</span><span class="o">*</span><span class="n">I</span> <span class="o">+</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">w_test</span> <span class="o">=</span> <span class="n">z_test</span><span class="o">**</span><span class="mi">7</span>
<span class="n">x_test</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">w_test</span><span class="p">.</span><span class="n">imag</span><span class="p">())</span>
<span class="n">y_test</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">w_test</span><span class="p">.</span><span class="n">imag</span><span class="p">())</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">x_test</span> <span class="o">+</span> <span class="n">a</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">y_test</span> <span class="o">+</span> <span class="n">b</span>
<span class="k">assert</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
<span class="k">assert</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="n">a</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="n">q</span> <span class="o">-</span> <span class="n">b</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span> <span class="o">==</span> <span class="n">w</span>
</code></pre></div></div>
<p>Finally, with <code class="language-plaintext highlighter-rouge">p,q</code> we can solve for the flag</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">3515251100858858796435724523870761115321577101490666287216209907489403476079222276536571942496157069855565014771125798502774268554017196492328530962886884456876064742139864478104832820555776577341055529681241338289453827370647829795170813667</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">3413213301181339793171422358348736699126965473930685311400429872075816456893055375667482794611435574843396575239764759040242158681190020317082329009191911152126267671754529169503180596722173728126136891139303943035843711591741985591269095977</span>
<span class="n">phi</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mh">0x10001</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">phi</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">flag_enc</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">p</span><span class="o">*</span><span class="n">q</span><span class="p">)))</span>
<span class="sa">b</span><span class="s">'CCTF{Congrats_Y0u_5OLv3d_x**2+y**2=z**7}'</span>
</code></pre></div></div>
<h5 id="flag-4">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{Congrats_Y0u_5OLv3d_x**2+y**2=z**7}</code></p>
<h2 id="rsaphantine">RSAphantine</h2>
<h3 id="challenge-5">Challenge</h3>
<blockquote>
<p><a href="https://cryp.toc.tf/tasks/RSAphantine_b1f2e30c7e90cfacb9ef4d0b5ce80abe33d1eb08.txz">RSA</a> and solving equations, but should be a real mathematician to solve it with a diophantine equation?</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">2</span><span class="o">*</span><span class="n">z</span><span class="o">**</span><span class="mi">5</span> <span class="o">-</span> <span class="n">x</span><span class="o">**</span><span class="mi">3</span> <span class="o">+</span> <span class="n">y</span><span class="o">*</span><span class="n">z</span> <span class="o">=</span> <span class="mi">47769864706750161581152919266942014884728504309791272300873440765010405681123224050402253883248571746202060439521835359010439155922618613520747411963822349374260144229698759495359592287331083229572369186844312169397998958687629858407857496154424105344376591742814310010312178029414792153520127354594349356721</span>
<span class="n">x</span><span class="o">**</span><span class="mi">4</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">5</span> <span class="o">+</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="o">*</span><span class="n">z</span> <span class="o">=</span> <span class="mi">89701863794494741579279495149280970802005356650985500935516314994149482802770873012891936617235883383779949043375656934782512958529863426837860653654512392603575042842591799236152988759047643602681210429449595866940656449163014827637584123867198437888098961323599436457342203222948370386342070941174587735051</span>
<span class="n">y</span><span class="o">**</span><span class="mi">6</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">z</span><span class="o">**</span><span class="mi">5</span> <span class="o">+</span> <span class="n">z</span><span class="o">*</span><span class="n">y</span> <span class="o">=</span> <span class="mi">47769864706750161581152919266942014884728504309791272300873440765010405681123224050402253883248571746202060439521835359010439155922618613609786612391835856376321085593999733543104760294208916442207908167085574197779179315081994735796390000652436258333943257231020011932605906567086908226693333446521506911058</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">z</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o"><<</span> <span class="mi">76</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">nextPrime</span><span class="p">(</span><span class="n">z</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">3</span> <span class="o">-</span> <span class="n">y</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">z</span> <span class="o">^</span> <span class="mi">67</span><span class="p">)</span>
<span class="n">n</span><span class="p">,</span> <span class="n">e</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span><span class="p">,</span> <span class="mi">31337</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">FLAG</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">486675922771716096231737399040548486325658137529857293201278143425470143429646265649376948017991651364539656238516890519597468182912015548139675971112490154510727743335620826075143903361868438931223801236515950567326769413127995861265368340866053590373839051019268657129382281794222269715218496547178894867320406378387056032984394810093686367691759705672</span>
</code></pre></div></div>
<h3 id="solution-5">Solution</h3>
<p>This challenge gives us the following set of three equations and three unknowns $x$, $y$, and $z$; it then generates parameters for RSA encryption using the following equations:</p>
\[p = \text{nextPrime}(\frac{x^2+y^2+z^2}{2^{76}})\\
q = \text{nextPrime}(z^2+y^3- (xyz \oplus 67))\]
<p>It doesn’t look like we can attack the equations for $p$ or $q$ directly, so we solve the diophantine equations first:</p>
\[2z^5-x^3+yz=47769... = a\\
x^4+y^5+xyz=89701... = b\\
y^6+2z^5+yz=47769... = c\]
<p>Note that while the right hand side of the first and third equations appear to be the same, they are different numbers. We first compute $c-a = x^3+y^6 = (x+y^2)(x^2-xy^2+y^4)$ by sum of cubes; factoring $c-a$, we recover the factors $3133713317731333$ and $28413320364759425…$.</p>
<p>Plugging the equations into z3, we solve for $x$, $y$, and $z$:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">z3</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">A</span> <span class="o">=</span> <span class="mi">3133713317731333</span>
<span class="n">B</span> <span class="o">=</span> <span class="mi">28413320364759425177418147555143516002041291710972733253944530195017276664069717887927099709630886727522090965378073004342203980057853092114878433424202989</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">486675922771716096231737399040548486325658137529857293201278143425470143429646265649376948017991651364539656238516890519597468182912015548139675971112490154510727743335620826075143903361868438931223801236515950567326769413127995861265368340866053590373839051019268657129382281794222269715218496547178894867320406378387056032984394810093686367691759705672</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">Int</span><span class="p">(</span><span class="s">"x"</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">Int</span><span class="p">(</span><span class="s">"y"</span><span class="p">)</span>
<span class="n">z</span> <span class="o">=</span> <span class="n">Int</span><span class="p">(</span><span class="s">"z"</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">Solver</span><span class="p">()</span>
<span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">x</span> <span class="o">==</span> <span class="n">A</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">y</span><span class="o">**</span><span class="mi">4</span> <span class="o">-</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">==</span> <span class="n">B</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">y</span><span class="o">></span><span class="mi">0</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">z</span><span class="o">**</span><span class="mi">5</span> <span class="o">-</span> <span class="n">x</span><span class="o">**</span><span class="mi">3</span> <span class="o">+</span> <span class="n">y</span><span class="o">*</span><span class="n">z</span> <span class="o">==</span> <span class="mi">47769864706750161581152919266942014884728504309791272300873440765010405681123224050402253883248571746202060439521835359010439155922618613520747411963822349374260144229698759495359592287331083229572369186844312169397998958687629858407857496154424105344376591742814310010312178029414792153520127354594349356721</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">4</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">5</span> <span class="o">+</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="o">*</span><span class="n">z</span> <span class="o">==</span> <span class="mi">89701863794494741579279495149280970802005356650985500935516314994149482802770873012891936617235883383779949043375656934782512958529863426837860653654512392603575042842591799236152988759047643602681210429449595866940656449163014827637584123867198437888098961323599436457342203222948370386342070941174587735051</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">y</span><span class="o">**</span><span class="mi">6</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">z</span><span class="o">**</span><span class="mi">5</span> <span class="o">+</span> <span class="n">z</span><span class="o">*</span><span class="n">y</span> <span class="o">==</span> <span class="mi">47769864706750161581152919266942014884728504309791272300873440765010405681123224050402253883248571746202060439521835359010439155922618613609786612391835856376321085593999733543104760294208916442207908167085574197779179315081994735796390000652436258333943257231020011932605906567086908226693333446521506911058</span><span class="p">)</span>
<span class="k">if</span> <span class="n">s</span><span class="p">.</span><span class="n">check</span><span class="p">()</span> <span class="o">==</span> <span class="n">sat</span><span class="p">:</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">model</span><span class="p">()</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">x</span><span class="p">].</span><span class="n">as_long</span><span class="p">()</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">y</span><span class="p">].</span><span class="n">as_long</span><span class="p">()</span>
<span class="n">z</span> <span class="o">=</span> <span class="n">m</span><span class="p">[</span><span class="n">z</span><span class="p">].</span><span class="n">as_long</span><span class="p">()</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">nextprime</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">z</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o"><<</span> <span class="mi">76</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">nextprime</span><span class="p">(</span><span class="n">z</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">3</span> <span class="o">-</span> <span class="n">y</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">z</span> <span class="o">^</span> <span class="mi">67</span><span class="p">)</span>
<span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">31337</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span><span class="o">*</span><span class="n">q</span><span class="p">))[</span><span class="mi">2</span><span class="p">:]).</span><span class="n">decode</span><span class="p">())</span>
</code></pre></div></div>
<h5 id="flag-5">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{y0Ur_jO8_C4l13D_Diophantine_An4LySI5!}</code></p>
<h2 id="frozen">Frozen</h2>
<h3 id="challenge-6">Challenge</h3>
<p>The server implements a signature scheme where we can get the parameters, the public key, and a signature for one sample message. We have to forge the signature for a second message.</p>
<p>The key generation works as follows:</p>
<ul>
<li>Start with a prime $p$ and random $r$, which we know. We work in $\mathbb{Z}_p$, so everything below is implicitly done modulo $p$.</li>
<li>Pick a random $r$, which we don’t know.</li>
<li>Build the array $U_i = r^{i+1}s$.</li>
<li>For the public key $pub$, take $U$ and mask the bottom 32 bits of each element.</li>
<li>The remaining bottom 32 bits of each element are the private key $priv$.</li>
</ul>
<p>To sign a message $M_i$, interpreted as an array of 32-bit integers:</p>
<ul>
<li>Let $q$ be a prime larger than all elements of $M$.</li>
<li>The signature is $sig_i = M_i priv_i \text{ mod } q$.</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">gmpy2</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">sys</span><span class="p">,</span> <span class="n">random</span><span class="p">,</span> <span class="n">string</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">'fakeflag{}'</span>
<span class="k">def</span> <span class="nf">genrandstr</span><span class="p">(</span><span class="n">N</span><span class="p">):</span>
<span class="k">return</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">choice</span><span class="p">(</span><span class="n">string</span><span class="p">.</span><span class="n">ascii_uppercase</span> <span class="o">+</span> <span class="n">string</span><span class="p">.</span><span class="n">digits</span> <span class="o">+</span> <span class="n">string</span><span class="p">.</span><span class="n">ascii_lowercase</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">N</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">paramaker</span><span class="p">(</span><span class="n">nbit</span><span class="p">):</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">getPrime</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">return</span> <span class="n">p</span><span class="p">,</span> <span class="n">r</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">l</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
<span class="n">p</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="n">params</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">U</span> <span class="o">=</span> <span class="p">[</span><span class="nb">pow</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">*</span> <span class="n">s</span> <span class="o">%</span> <span class="n">p</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">l</span><span class="p">)]</span>
<span class="n">V</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">u</span><span class="p">)[</span><span class="mi">2</span><span class="p">:][:</span><span class="o">-</span><span class="n">d</span><span class="p">]</span> <span class="o">+</span> <span class="s">'0'</span> <span class="o">*</span> <span class="n">d</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="n">U</span><span class="p">]</span>
<span class="n">S</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">u</span><span class="p">)[</span><span class="mi">2</span><span class="p">:][</span><span class="o">-</span><span class="n">d</span><span class="p">:],</span> <span class="mi">2</span><span class="p">)</span> <span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="n">U</span><span class="p">]</span>
<span class="n">privkey</span><span class="p">,</span> <span class="n">pubkey</span> <span class="o">=</span> <span class="n">S</span><span class="p">,</span> <span class="n">V</span>
<span class="k">return</span> <span class="n">pubkey</span><span class="p">,</span> <span class="n">privkey</span>
<span class="k">def</span> <span class="nf">sign</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">privkey</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="o">//</span> <span class="mi">4</span>
<span class="n">M</span> <span class="o">=</span> <span class="p">[</span><span class="n">bytes_to_long</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">4</span><span class="o">*</span><span class="n">i</span><span class="p">:</span><span class="mi">4</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)])</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">)]</span>
<span class="n">q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">next_prime</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">M</span><span class="p">)))</span>
<span class="n">sign</span> <span class="o">=</span> <span class="p">[</span><span class="n">M</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="n">privkey</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">%</span> <span class="n">q</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">)]</span>
<span class="k">return</span> <span class="n">sign</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" hi young cryptographers, welcome to the frozen signature battle!! "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" Your mission is to forge the signature for a given message, ready?!"</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">randstr</span> <span class="o">=</span> <span class="n">genrandstr</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
<span class="n">nbit</span><span class="p">,</span> <span class="n">dbit</span> <span class="o">=</span> <span class="mi">128</span><span class="p">,</span> <span class="mi">32</span>
<span class="n">params</span> <span class="o">=</span> <span class="n">paramaker</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="mi">5</span>
<span class="n">pubkey</span><span class="p">,</span> <span class="n">privkey</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">l</span><span class="p">,</span> <span class="n">dbit</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[S]how the params </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[P]rint pubkey </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[E]xample signature </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[F]orge the signature </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'s'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| p = </span><span class="si">{</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| r = </span><span class="si">{</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'p'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'pubkey = </span><span class="si">{</span><span class="n">pubkey</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'e'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| the signature for "</span><span class="si">{</span><span class="n">randstr</span><span class="si">}</span><span class="s">" is :'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| signature = </span><span class="si">{</span><span class="n">sign</span><span class="p">(</span><span class="n">randstr</span><span class="p">,</span> <span class="n">privkey</span><span class="p">,</span> <span class="n">dbit</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'f'</span><span class="p">:</span>
<span class="n">randmsg</span> <span class="o">=</span> <span class="n">genrandstr</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| send the signature of the following message like example: </span><span class="si">{</span><span class="n">randmsg</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">SIGN</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">SIGN</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">SIGN</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)]</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| your signature is not valid! Bye!!'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">SIGN</span> <span class="o">==</span> <span class="n">sign</span><span class="p">(</span><span class="n">randmsg</span><span class="p">,</span> <span class="n">privkey</span><span class="p">,</span> <span class="n">dbit</span><span class="p">):</span>
<span class="n">die</span><span class="p">(</span><span class="sa">f</span><span class="s">'| Congrats, you got the flag: </span><span class="si">{</span><span class="n">FLAG</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="sa">f</span><span class="s">'| Your signature is not correct, try later! Bye!'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<h3 id="solution-6">Solution</h3>
<p>If we look at the first element of the signature, we have:</p>
\[sig_0 = M_0 priv_0 \text{ mod } q\]
<p>Since we can compute $q$ (as we know the message $M$), we can find the multiplicative inverse of $M_0$ and recover the first element of the private key modulo $q$:</p>
\[priv_0 = M_0^{-1} sig_0 \text{ mod } q\]
<p>The real private key is 32 bits long, and $q$ is around $2^{30}$, so around one try in four this will be the real value of $priv_0$. If this doesn’t work, we can proceed by trying $M^0{-1} sig_0 + kq$ for increasing values of $k$, and will recover the correct $priv_0$ in a
few tries.</p>
<p>For each candidate value, we can combine it with $pub_0$ to get $U_0 = rs$. Since we know $r$, we have $s = U_0 r^{-1}$ (in $\mathbb{Z}_p$), which we can use to re-generate the entire public and private key and see if the public key matches the one we were given.</p>
<p>Once we find one that does, all that’s left is to use the provided signing function to forge the signature.</p>
<p>Here is a hacky script written during the CTF – it doesn’t work properly when the recovered $priv_0$ is wrapped by the modulus, but that just means we need to run it a few times to get the flag:</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#! /usr/bin/env python
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">gmpy2</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">l</span> <span class="o">=</span> <span class="mi">5</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">l</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">s</span><span class="p">):</span>
<span class="n">p</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="n">params</span>
<span class="n">U</span> <span class="o">=</span> <span class="p">[</span><span class="nb">pow</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">*</span> <span class="n">s</span> <span class="o">%</span> <span class="n">p</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">l</span><span class="p">)]</span>
<span class="n">V</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">u</span><span class="p">)[</span><span class="mi">2</span><span class="p">:][:</span><span class="o">-</span><span class="n">d</span><span class="p">]</span> <span class="o">+</span> <span class="s">'0'</span> <span class="o">*</span> <span class="n">d</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="n">U</span><span class="p">]</span>
<span class="n">S</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">u</span><span class="p">)[</span><span class="mi">2</span><span class="p">:][</span><span class="o">-</span><span class="n">d</span><span class="p">:],</span> <span class="mi">2</span><span class="p">)</span> <span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="n">U</span><span class="p">]</span>
<span class="n">privkey</span><span class="p">,</span> <span class="n">pubkey</span> <span class="o">=</span> <span class="n">S</span><span class="p">,</span> <span class="n">V</span>
<span class="k">return</span> <span class="n">pubkey</span><span class="p">,</span> <span class="n">privkey</span>
<span class="k">def</span> <span class="nf">sign</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">privkey</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> <span class="o">//</span> <span class="mi">4</span>
<span class="n">M</span> <span class="o">=</span> <span class="p">[</span><span class="n">bytes_to_long</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">4</span><span class="o">*</span><span class="n">i</span><span class="p">:</span><span class="mi">4</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)])</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">)]</span>
<span class="n">q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">next_prime</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">M</span><span class="p">)))</span>
<span class="n">sign</span> <span class="o">=</span> <span class="p">[</span><span class="n">M</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="n">privkey</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">%</span> <span class="n">q</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">)]</span>
<span class="k">return</span> <span class="n">sign</span>
<span class="k">def</span> <span class="nf">break_key</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="n">sig</span><span class="p">):</span>
<span class="n">q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">next_prime</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">msg</span><span class="p">)))</span>
<span class="n">pk0_base</span> <span class="o">=</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">q</span><span class="p">))</span> <span class="o">%</span> <span class="n">q</span>
<span class="k">print</span><span class="p">(</span><span class="n">pk0_base</span><span class="p">,</span> <span class="n">sig</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">pow</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">q</span><span class="p">))</span>
<span class="k">for</span> <span class="n">pk0</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">pk0_base</span><span class="p">,</span> <span class="n">q</span><span class="p">,</span> <span class="mi">2</span><span class="o">**</span><span class="mi">32</span><span class="p">):</span>
<span class="n">rs</span> <span class="o">=</span> <span class="n">pubkey</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">pk0</span>
<span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="n">rs</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">outpub</span><span class="p">,</span> <span class="n">outpriv</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">((</span><span class="n">p</span><span class="p">,</span> <span class="n">r</span><span class="p">),</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">pubkey</span><span class="p">,</span> <span class="n">outpub</span><span class="p">)</span>
<span class="k">if</span> <span class="n">outpub</span> <span class="o">==</span> <span class="n">pubkey</span><span class="p">:</span>
<span class="k">return</span> <span class="n">outpub</span><span class="p">,</span> <span class="n">outpriv</span>
<span class="k">raise</span> <span class="nb">Exception</span><span class="p">(</span><span class="s">"Could not find key!"</span><span class="p">)</span>
<span class="n">serv</span> <span class="o">=</span> <span class="n">pwnlib</span><span class="p">.</span><span class="n">tubes</span><span class="p">.</span><span class="n">remote</span><span class="p">.</span><span class="n">remote</span><span class="p">(</span><span class="s">'03.cr.yp.toc.tf'</span><span class="p">,</span> <span class="mi">25010</span><span class="p">)</span>
<span class="c1">#serv = pwnlib.tubes.process.process('./frozen.py')
</span>
<span class="n">serv</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'[Q]uit'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'s'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="n">p</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">serv</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">rstrip</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="n">r</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">serv</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">rstrip</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="s">'p ='</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'r ='</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'[Q]uit'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'e'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="n">msg_b</span> <span class="o">=</span> <span class="n">serv</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">'"'</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sig</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">serv</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">'='</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span> <span class="c1"># lol
</span><span class="n">msg</span> <span class="o">=</span> <span class="p">[</span><span class="n">bytes_to_long</span><span class="p">(</span><span class="n">msg_b</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)[</span><span class="mi">4</span><span class="o">*</span><span class="n">i</span><span class="p">:</span><span class="mi">4</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)])</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="p">)]</span>
<span class="k">print</span><span class="p">(</span><span class="s">'msg ='</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'sig ='</span><span class="p">,</span> <span class="n">sig</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'[Q]uit'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'p'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="n">pubkey</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">serv</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">'='</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span> <span class="c1"># lol again
</span>
<span class="k">print</span><span class="p">(</span><span class="s">'pubkey ='</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">)</span>
<span class="n">pub</span><span class="p">,</span> <span class="n">priv</span> <span class="o">=</span> <span class="n">break_key</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="n">sig</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'[Q]uit'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'f'</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="n">forge</span> <span class="o">=</span> <span class="n">serv</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">rstrip</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">forge_sig</span> <span class="o">=</span> <span class="n">sign</span><span class="p">(</span><span class="n">forge</span><span class="p">,</span> <span class="n">priv</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
<span class="n">serv</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">','</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">forge_sig</span><span class="p">))</span>
<span class="n">serv</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<h5 id="flag-6">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{Lattice_bA5eD_T3cHn1QuE_70_Br34K_LCG!!}</code></p>
<h2 id="linda">LINDA</h2>
<h3 id="challenge-7">Challenge</h3>
<blockquote>
<p>Dan Boneh loves to improve cryptosystems, you should be loving breaking them?
<code class="language-plaintext highlighter-rouge">nc 07.cr.yp.toc.tf 31010</code></p>
<ul>
<li><a href="https://cr.yp.toc.tf/tasks/linda_a26f6987ed6c630297c2df0847ef258ad3810ca2.txz">linda.txz</a></li>
</ul>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">u</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">w</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">gcd</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">v</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">return</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">w</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">):</span>
<span class="n">p</span><span class="p">,</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">w</span> <span class="o">=</span> <span class="n">pubkey</span>
<span class="k">assert</span> <span class="n">m</span> <span class="o"><</span> <span class="n">p</span>
<span class="n">r</span><span class="p">,</span> <span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="s">'01'</span><span class="p">]</span>
<span class="n">ca</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">cb</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">cc</span> <span class="o">=</span> <span class="n">m</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span> <span class="o">+</span> <span class="n">s</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">enc</span> <span class="o">=</span> <span class="p">(</span><span class="n">ca</span><span class="p">,</span> <span class="n">cb</span><span class="p">,</span> <span class="n">cc</span><span class="p">)</span>
<span class="k">return</span> <span class="n">enc</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" .:::::: LINDA Cryptosystem has high grade security level ::::::. "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" Can you break this cryptosystem and find the flag? "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| please wait, preparing the LINDA is time consuming...'</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">p</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">w</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">pubkey</span> <span class="o">=</span> <span class="n">p</span><span class="p">,</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">w</span>
<span class="n">enc</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[E]xpose the parameters </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[T]est the encryption </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[S]how the encrypted flag </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'e'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| p = </span><span class="si">{</span><span class="n">p</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| u = </span><span class="si">{</span><span class="n">u</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| v = </span><span class="si">{</span><span class="n">v</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| w = </span><span class="si">{</span><span class="n">w</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'s'</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'enc = </span><span class="si">{</span><span class="n">enc</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'t'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| send your message to encrypt: '</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| encrypt(m) = </span><span class="si">{</span><span class="n">encrypt</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<h3 id="solution-7">Solution</h3>
<p>By interacting with the challenge, we can get public key parameters by sending <code class="language-plaintext highlighter-rouge">e</code>, get encrypted flag with <code class="language-plaintext highlighter-rouge">s</code>, encrypt our own messages with <code class="language-plaintext highlighter-rouge">t</code> and quit with <code class="language-plaintext highlighter-rouge">q</code>. Only the first two options will be relevant to the solution.</p>
<p>Encryption here works like this: $p, u, v, w$ are public key parameters, message $m$ is encrypted as
follows:</p>
\[ca \equiv u^r \mod p \\
cb \equiv v^s \mod p$ \\
cc \equiv mw^{r + s} \mod p\]
<p>where $r, s$ are uniformly random numbers from $[1;p]$.</p>
<p>We can notice that despite $p$ being new on each connection, $p - 1$ is always smooth. Example:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">p</span> <span class="o">=</span> <span class="mi">31236959722193405152010489304408176327538432524312583937104819646529142201202386217645408893898924349364771709996106640982219903602836751314429782819699</span>
<span class="n">p</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">11</span> <span class="o">*</span> <span class="mi">41</span> <span class="o">*</span> <span class="mi">137</span> <span class="o">*</span> <span class="mi">223</span> <span class="o">*</span> <span class="mi">7529</span> <span class="o">*</span> <span class="mi">14827</span> <span class="o">*</span> <span class="mi">15121</span> <span class="o">*</span> <span class="mi">40559</span> <span class="o">*</span> <span class="mi">62011</span> <span class="o">*</span> <span class="mi">429083</span> <span class="o">*</span> <span class="mi">916169</span> <span class="o">*</span> <span class="mi">3810461</span> <span class="o">*</span> <span class="mi">4316867</span> <span class="o">*</span> <span class="mi">20962993</span> <span class="o">*</span> <span class="mi">31469027</span> <span class="o">*</span> <span class="mi">81724477</span> <span class="o">*</span> <span class="mi">132735437</span> <span class="o">*</span> <span class="mi">268901797</span> <span class="o">*</span> <span class="mi">449598857</span> <span class="o">*</span> <span class="mi">2101394579</span> <span class="o">*</span> <span class="mi">2379719473</span> <span class="o">*</span> <span class="mi">5859408629</span> <span class="o">*</span> <span class="mi">11862763021</span> <span class="o">*</span> <span class="mi">45767566217</span>
</code></pre></div></div>
<p>This is the key for solving this challenge, because after getting public key paramters and encrypted flag we can factor $p - 1$ by using trial division and <a href="https://en.wikipedia.org/wiki/Lenstra_elliptic-curve_factorization">ECM</a>, then use <a href="https://en.wikipedia.org/wiki/Pohlig%E2%80%93Hellman_algorithm">Pohlig-Hellman algorithm</a> to compute $r, s$ as discrete logarithms of $ca, cb$ with bases $u, v$ respectively even without trying to find weaknesses in the keygen process. Then we can compute $m \equiv ccw^{-(r + s)} \mod p$ and get the flag.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env sage
</span><span class="kn">from</span> <span class="nn">minipwn</span> <span class="kn">import</span> <span class="n">remote</span> <span class="c1"># mini-pwntools library to connect to server
</span><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="n">rem</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"07.cr.yp.toc.tf"</span><span class="p">,</span> <span class="mi">31010</span><span class="p">)</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">rem</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">rem</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'e'</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">rem</span><span class="p">.</span><span class="n">recvline</span><span class="p">()[</span><span class="mi">6</span><span class="p">:])</span>
<span class="n">u</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">rem</span><span class="p">.</span><span class="n">recvline</span><span class="p">()[</span><span class="mi">6</span><span class="p">:])</span>
<span class="n">v</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">rem</span><span class="p">.</span><span class="n">recvline</span><span class="p">()[</span><span class="mi">6</span><span class="p">:])</span>
<span class="n">w</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">rem</span><span class="p">.</span><span class="n">recvline</span><span class="p">()[</span><span class="mi">6</span><span class="p">:])</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="n">rem</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">rem</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'s'</span><span class="p">)</span>
<span class="n">ca</span><span class="p">,</span> <span class="n">cb</span><span class="p">,</span> <span class="n">cc</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">rem</span><span class="p">.</span><span class="n">recvline</span><span class="p">()[</span><span class="mi">7</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s">', '</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">discrete_log</span><span class="p">(</span><span class="n">Mod</span><span class="p">(</span><span class="n">ca</span><span class="p">,</span> <span class="n">p</span><span class="p">),</span> <span class="n">Mod</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">p</span><span class="p">))</span> <span class="c1"># sage has built-in discrete logarithm function, which uses Pohlig-Hellman
</span><span class="n">s</span> <span class="o">=</span> <span class="n">discrete_log</span><span class="p">(</span><span class="n">Mod</span><span class="p">(</span><span class="n">cb</span><span class="p">,</span> <span class="n">p</span><span class="p">),</span> <span class="n">Mod</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">p</span><span class="p">))</span> <span class="c1"># algorithm and automatically determines and factors group order, which divides p - 1
</span><span class="n">m</span> <span class="o">=</span> <span class="n">cc</span> <span class="o">*</span> <span class="n">power_mod</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="o">-</span><span class="p">(</span><span class="n">r</span> <span class="o">+</span> <span class="n">s</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">m</span><span class="p">).</span><span class="n">decode</span><span class="p">())</span>
</code></pre></div></div>
<h5 id="flag-7">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{1mPr0v3D_CrYp7O_5yST3m_8Y_Boneh_Boyen_Shacham!}</code></p>["CryptoHackers"]Last week, CryptoHackers got together to play CryptoCTF for the second time as a team. We solved 26/29 of the challenges during the 24 hour window and came third overall. First and second places went to Super Guessers (Rkm and Rbtree are very friendly faces from CryptoHack) and a Vietnamese team working together to support the spirit of Ho Chi Minh city and nearby provinces. Congratulations to them both.CryptoCTF 2021 - Hard2021-08-04T00:00:00+00:002021-08-04T00:00:00+00:00https://blog.cryptohack.org/cryptoctf-hard<p>Last week, CryptoHackers got together to play CryptoCTF for the second time as a team. We solved 26/29 of the challenges during the 24 hour window and came third overall. First and second places went to Super Guessers (Rkm and Rbtree are very friendly faces from CryptoHack) and a Vietnamese team working together to support the spirit of Ho Chi Minh city and nearby provinces. Congratulations to them both.</p>
<p><img src="/assets/images/cryptoctf-2021.png" alt="CTF Scoreboard" /></p>
<p>Not only was it a lot of fun for us all to play together, but it was amazing to see how many CryptoHack friends played the CTF either solo or in small teams and who were able to get a top 15 spot. We’re honoured to have so many talented people in our Discord, chatting with us about maths and cryptography. We even have guest writeups from <a href="https://rkm0959.tistory.com">rkm0959</a> talking about the solutions of <a href="#dorsa">DoRSA</a> and <a href="#polish">Polish</a>.</p>
<p>Here are the write-ups for the hardest challenges in the CTF. You can find write ups for the <a href="https://blog.cryptohack.org/cryptoctf2021-easy">easy</a> and <a href="https://blog.cryptohack.org/cryptoctf2021-medium">medium</a> challenges as other posts on our blog.</p>
<p>Thank you to everyone who played for the CryptoHackers, and to ASIS CTF for organising this enjoyable event. Congratulations again to Super Guessers for being the ultimate crypto heros!</p>
<p><em>We will be publishing more writeups here as soon as they are finished. If you spot a mistake or an improvement that could be made, please ping jack or hyperreality on CryptoHack Discord.</em></p>
<h2 id="challenges">Challenges</h2>
<table>
<thead>
<tr>
<th>Challenge Name</th>
<th>Category</th>
<th>Solved By</th>
<th style="text-align: right">Points</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#tiny-ecc">Tiny ECC</a></td>
<td>Elliptic Curves</td>
<td>Jack</td>
<td style="text-align: right">217</td>
</tr>
<tr>
<td><a href="#elegant-curve">Elegant Curve</a></td>
<td>Elliptic Curves</td>
<td>Jack</td>
<td style="text-align: right">217</td>
</tr>
<tr>
<td><a href="#double-miff">Double Miff</a></td>
<td>Elliptic Curves</td>
<td>NeketmanX</td>
<td style="text-align: right">217</td>
</tr>
<tr>
<td><a href="#ecchimera">Ecchimera</a></td>
<td>Elliptic Curves</td>
<td>Vishiswoz, Kubie, NeketmanX</td>
<td style="text-align: right">271</td>
</tr>
<tr>
<td><a href="#rohald">RoHaLd</a></td>
<td>Elliptic Curves</td>
<td>Jack, Esrever, Vishiswoz, UnblvR</td>
<td style="text-align: right">180</td>
</tr>
<tr>
<td><a href="#robert">Robert</a></td>
<td>Carmichael Lambda</td>
<td>Robin, DD</td>
<td style="text-align: right">194</td>
</tr>
<tr>
<td><a href="#trunc">Trunc</a></td>
<td>Signature forgery</td>
<td>NeketmanX</td>
<td style="text-align: right">334</td>
</tr>
<tr>
<td><a href="#my-sieve">My Sieve</a></td>
<td>RSA</td>
<td>Solved after end</td>
<td style="text-align: right">477</td>
</tr>
<tr>
<td><a href="#dorsa">DoRSA</a></td>
<td>RSA</td>
<td>Super Guesser (Guest Post)</td>
<td style="text-align: right">450</td>
</tr>
<tr>
<td><a href="#polish">Polish</a></td>
<td>RSA</td>
<td>Super Guesser (Guest Post)</td>
<td style="text-align: right">477</td>
</tr>
</tbody>
</table>
<h2 id="tiny-ecc">Tiny ECC</h2>
<h3 id="challenge">Challenge</h3>
<blockquote>
<p>Being Smart will mean completely different if you can use <a href="https://cr.yp.toc.tf/tasks/tiny_ecc_f6ba20693ddf6ba78f1537889d2c46a17b7a4d8b.txz">special numbers</a>!</p>
<p><code class="language-plaintext highlighter-rouge">nc 01.cr.yp.toc.tf 29010</code></p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">mini_ecdsa</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">def</span> <span class="nf">tonelli_shanks</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="n">q</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">q</span> <span class="o">//</span> <span class="mi">2</span>
<span class="n">s</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">if</span> <span class="n">s</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">r1</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">4</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
<span class="n">r2</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">r1</span>
<span class="k">return</span> <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">z</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="n">q</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">z</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">r</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">q</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">q</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">s</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="n">t</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">r1</span> <span class="o">=</span> <span class="n">r</span>
<span class="n">r2</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">r1</span>
<span class="k">return</span> <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="mi">2</span><span class="o">**</span><span class="n">i</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">b</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mi">2</span><span class="o">**</span><span class="p">(</span><span class="n">m</span><span class="o">-</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">r</span> <span class="o">*</span> <span class="n">b</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">t</span> <span class="o">*</span> <span class="n">b</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">b</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">i</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">def</span> <span class="nf">random_point</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">gx</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">n</span> <span class="o">=</span> <span class="p">(</span><span class="n">gx</span><span class="o">**</span><span class="mi">3</span> <span class="o">+</span> <span class="n">a</span><span class="o">*</span><span class="n">gx</span> <span class="o">+</span> <span class="n">b</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">gy</span> <span class="o">=</span> <span class="n">tonelli_shanks</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">if</span> <span class="n">gy</span> <span class="o">==</span> <span class="bp">False</span><span class="p">:</span>
<span class="k">continue</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="p">(</span><span class="n">gx</span><span class="p">,</span> <span class="n">gy</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" Dual ECC means two elliptic curve with same coefficients over the "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" different fields or ring! You should calculate the discrete log "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" in dual ECCs. So be smart in choosing the first parameters! Enjoy!"</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">bool_coef</span><span class="p">,</span> <span class="n">bool_prime</span><span class="p">,</span> <span class="n">nbit</span> <span class="o">=</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="mi">128</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[C]hoose the </span><span class="si">{</span><span class="n">nbit</span><span class="si">}</span><span class="s">-bit prime p </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[A]ssign the coefficients </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[S]olve DLP </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'a'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| send the coefficients a and b separated by comma: '</span><span class="p">)</span>
<span class="n">COEFS</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">_</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">COEFS</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)]</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| your coefficients are not valid, Bye!!'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">a</span><span class="o">*</span><span class="n">b</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| Kidding me?!! a*b should not be zero!!'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">bool_coef</span> <span class="o">=</span> <span class="bp">True</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'c'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| send your prime: '</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">p</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| your input is not valid :('</span><span class="p">)</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="ow">and</span> <span class="n">p</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">==</span> <span class="n">nbit</span> <span class="ow">and</span> <span class="n">isPrime</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">bool_prime</span> <span class="o">=</span> <span class="bp">True</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="sa">f</span><span class="s">'| your integer p is not </span><span class="si">{</span><span class="n">nbit</span><span class="si">}</span><span class="s">-bit prime or 2p + 1 is not prime, bye!!'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'s'</span><span class="p">:</span>
<span class="k">if</span> <span class="n">bool_coef</span> <span class="o">==</span> <span class="bp">False</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| please assign the coefficients.'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">bool_prime</span> <span class="o">==</span> <span class="bp">False</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| please choose your prime first.'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">bool_prime</span> <span class="ow">and</span> <span class="n">bool_coef</span><span class="p">:</span>
<span class="n">Ep</span> <span class="o">=</span> <span class="n">CurveOverFp</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">Eq</span> <span class="o">=</span> <span class="n">CurveOverFp</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">q</span><span class="p">)</span>
<span class="n">xp</span><span class="p">,</span> <span class="n">yp</span> <span class="o">=</span> <span class="n">random_point</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">Point</span><span class="p">(</span><span class="n">xp</span><span class="p">,</span> <span class="n">yp</span><span class="p">)</span>
<span class="n">xq</span><span class="p">,</span> <span class="n">yq</span> <span class="o">=</span> <span class="n">random_point</span><span class="p">(</span><span class="n">q</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">=</span> <span class="n">Point</span><span class="p">(</span><span class="n">xq</span><span class="p">,</span> <span class="n">yq</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span> <span class="o">>></span> <span class="mi">1</span><span class="p">)</span>
<span class="n">kP</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">.</span><span class="n">mult</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">q</span> <span class="o">>></span> <span class="mi">1</span><span class="p">)</span>
<span class="n">lQ</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">.</span><span class="n">mult</span><span class="p">(</span><span class="n">Q</span><span class="p">,</span> <span class="n">l</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| We know that: '</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| P = </span><span class="si">{</span><span class="n">P</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| k*P = </span><span class="si">{</span><span class="n">kP</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| Q = </span><span class="si">{</span><span class="n">Q</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">'| l*Q = </span><span class="si">{</span><span class="n">lQ</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">'| send the k and l separated by comma: '</span><span class="p">)</span>
<span class="n">PRIVS</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">priv</span><span class="p">,</span> <span class="n">qriv</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">PRIVS</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)]</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| your input is not valid, Bye!!'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">priv</span> <span class="o">==</span> <span class="n">k</span> <span class="ow">and</span> <span class="n">qriv</span> <span class="o">==</span> <span class="n">l</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="sa">f</span><span class="s">'| Congrats, you got the flag: </span><span class="si">{</span><span class="n">flag</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| sorry, your keys are not correct! Bye!!!'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<p>The challenge is to supply $a,b,p,q=2p+1$ to generate two curves</p>
\[E_p: y^2 = x^3 + ax + b \pmod p \\
E_q: y^2 = x^3 + ax + b \pmod q\]
<p>The goal of the challenge is to solve the discrete log for a pair of points on each of these curves. Submitting the correct private keys gives you the flag.</p>
<h3 id="solution">Solution</h3>
<p>I solved this challenge in a fairly ugly and inelegant way. So I’ll go through it quickly, then discuss what seems to be the intended solution after.</p>
<p>My idea was to generate a curve $E_p$ with $\#E_p = p$. This is an anomalous curve, and using Smart’s attack, the discrete log problem can be moved to solving a simple division by lifting the curve of the p-adics, which is just division! Then after making one curve easy, I would keep generating primes $p$ until I found a $(q,a,b)$ where $E_q$ had a smooth order, allowing us to solve the discrete log easily.</p>
<h4 id="generating-anomalous-curves">Generating anomalous curves</h4>
<p>I refered to <a href="http://www.monnerat.info/publications/anomalous.pdf">Generating Anomalous Elliptic Curves</a> to generate anomalous curves, and iterated through all primes $p$ where $E_p$ was anomalous. If $q = 2p + 1$ was prime, then I stored the tuple $(p,a,b)$ in a list. I did this until I had plenty of curves to look through.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># http://www.monnerat.info/publications/anomalous.pdf
</span><span class="n">D</span> <span class="o">=</span> <span class="mi">19</span>
<span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">2</span><span class="o">^</span><span class="mi">15</span><span class="o">*</span><span class="mi">3</span><span class="o">^</span><span class="mi">3</span>
<span class="k">def</span> <span class="nf">anon_prime</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="mi">19</span><span class="o">*</span><span class="n">m</span><span class="o">*</span><span class="p">(</span><span class="n">m</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">+</span> <span class="mi">5</span>
<span class="k">if</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
<span class="k">return</span> <span class="n">m</span><span class="p">,</span> <span class="n">p</span>
<span class="n">m</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">curves</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">anom_curve</span><span class="p">():</span>
<span class="n">m</span> <span class="o">=</span> <span class="mi">2</span><span class="o">**</span><span class="mi">61</span> <span class="o">+</span> <span class="mi">2</span><span class="o">**</span><span class="mi">60</span> <span class="c1"># chosen so the curves have bit length 128
</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">m</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="n">anon_prime</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="o">*</span><span class="n">j</span> <span class="o">*</span> <span class="n">inverse_mod</span><span class="p">((</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1728</span><span class="p">),</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">j</span> <span class="o">*</span> <span class="n">inverse_mod</span><span class="p">((</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1728</span><span class="p">),</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="k">if</span> <span class="n">E</span><span class="p">.</span><span class="n">order</span><span class="p">()</span> <span class="o">==</span> <span class="n">p</span><span class="p">:</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">E</span><span class="p">.</span><span class="n">gens</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Found an anomalous prime of bit length: </span><span class="si">{</span><span class="n">p</span><span class="p">.</span><span class="n">nbits</span><span class="p">()</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">is_prime</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Found an anomalous prime with safe prime q = 2p+1. p=</span><span class="si">{</span><span class="n">p</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">p</span><span class="p">.</span><span class="n">nbits</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">128</span><span class="p">:</span>
<span class="nb">exit</span><span class="p">()</span>
<span class="n">curves</span><span class="p">.</span><span class="n">append</span><span class="p">([</span><span class="n">p</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="n">curves</span><span class="p">)</span>
<span class="n">m</span> <span class="o">+=</span> <span class="mi">1</span>
</code></pre></div></div>
<p>Going through curves, I then looked to find $E_q$ of smooth order:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">curves</span><span class="p">:</span>
<span class="n">p</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">param</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">E1</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="n">E2</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="k">assert</span> <span class="n">E1</span><span class="p">.</span><span class="n">order</span><span class="p">()</span> <span class="o">==</span> <span class="n">p</span>
<span class="k">print</span><span class="p">(</span><span class="n">factor</span><span class="p">(</span><span class="n">E2</span><span class="p">.</span><span class="n">order</span><span class="p">()))</span>
</code></pre></div></div>
<p>Pretty quickly, I found a curve (I think the 15th one?) with order:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">E2</span><span class="p">.</span><span class="n">order</span><span class="p">()</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="mi">11</span> <span class="o">*</span> <span class="mi">29</span> <span class="o">*</span> <span class="mi">269</span> <span class="o">*</span> <span class="mi">809</span> <span class="o">*</span> <span class="mi">1153</span> <span class="o">*</span> <span class="mi">5527</span> <span class="o">*</span> <span class="mi">1739687</span> <span class="o">*</span> <span class="mi">272437559</span> <span class="o">*</span> <span class="mi">1084044811</span>
</code></pre></div></div>
<p>This is more than smooth enough to solve the dlog (about 10 seconds).</p>
<p>Sending the parameters to the server:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">p</span> <span class="o">=</span> <span class="mi">227297987279223760839521045903912023553</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">120959747616429018926294825597988269841</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">146658155534937748221991162171919843659</span>
</code></pre></div></div>
<p>I can solve this discrete log using Smart’s attack, and the inbuilt discrete log on $E_q$ as it has smooth order.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">SmartAttack</span><span class="p">(</span><span class="n">P</span><span class="p">,</span><span class="n">Q</span><span class="p">,</span><span class="n">p</span><span class="p">):</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">P</span><span class="p">.</span><span class="n">curve</span><span class="p">()</span>
<span class="n">Eqp</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Qp</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">[</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">+</span> <span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">p</span><span class="p">)</span><span class="o">*</span><span class="n">p</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">E</span><span class="p">.</span><span class="n">a_invariants</span><span class="p">()</span> <span class="p">])</span>
<span class="n">P_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">P_Qp</span> <span class="ow">in</span> <span class="n">P_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">P_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">Q_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">Q_Qp</span> <span class="ow">in</span> <span class="n">Q_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">Q_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">p_times_P</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">P_Qp</span>
<span class="n">p_times_Q</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">Q_Qp</span>
<span class="n">x_P</span><span class="p">,</span><span class="n">y_P</span> <span class="o">=</span> <span class="n">p_times_P</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">x_Q</span><span class="p">,</span><span class="n">y_Q</span> <span class="o">=</span> <span class="n">p_times_Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">phi_P</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_P</span><span class="o">/</span><span class="n">y_P</span><span class="p">)</span>
<span class="n">phi_Q</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_Q</span><span class="o">/</span><span class="n">y_Q</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">phi_Q</span><span class="o">/</span><span class="n">phi_P</span>
<span class="k">return</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">227297987279223760839521045903912023553</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">120959747616429018926294825597988269841</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">146658155534937748221991162171919843659</span>
<span class="n">Ep</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">97161828186858857945099901434400040095</span><span class="p">,</span><span class="mi">76112161730436240110429589963792144699</span><span class="p">)</span>
<span class="n">rG</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">194119107523766318610516779439078452539</span><span class="p">,</span><span class="mi">111570625156450061932127850545534033820</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">SmartAttack</span><span class="p">(</span><span class="n">G</span><span class="p">,</span><span class="n">rG</span><span class="p">,</span><span class="n">p</span><span class="p">))</span>
<span class="n">Eq</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="n">H</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">229869041108862357437180702478501205702</span><span class="p">,</span><span class="mi">238550780537940464808919616209960416466</span><span class="p">)</span>
<span class="n">sH</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">18599290990046241788386470878953668775</span><span class="p">,</span><span class="mi">281648589325596060237553465951876240185</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">H</span><span class="p">.</span><span class="n">discrete_log</span><span class="p">(</span><span class="n">sH</span><span class="p">))</span>
</code></pre></div></div>
<h5 id="flag">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{ECC_With_Special_Prime5}</code></p>
<h3 id="intended-solution">Intended Solution?</h3>
<p>Thanks to Ariana for suggeting this solution to me after the CTF ended.</p>
<p>The challenge checks for $a * b \neq 0$ , but it does not do this modulo the primes, so if we pick any two primes $p, q = 2p+1$ we can send</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">p</span> <span class="o">=</span> <span class="mi">227297987279223760839521045903912023553</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div>
<p>Such that the two curves are given by</p>
\[E_p: y^2 = x^3 + pq x + pq \pmod p = x^3 \\
E_q: y^2 = x^3 + pq x + pq \pmod q = x^3 \\\]
<p>Which are singular curves (in particular, these singular curves have triple zeros, known as cusps). We can translate the discrete log over these curves to solving in the additive group of $F_p$ and so the discrete log is division, and trivial. See this <a href="https://crypto.stackexchange.com/questions/61302/how-to-solve-this-ecdlp">link</a> for an example.</p>
<p>Basically, we use the homomorphism</p>
\[\phi(x,y) \to \frac{x}{y}\]
<p>such that we can solve this discrete log in the following way</p>
\[H = [k] G, \;\; g = \frac{G_x}{G_y}, \;\; h = \frac{H_x}{H_y}, \;\; k = \frac{h}{g}\]
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">p</span> <span class="o">=</span> <span class="mi">227297987279223760839521045903912023553</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">Fp</span> <span class="o">=</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">Fq</span> <span class="o">=</span> <span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
<span class="n">Px</span><span class="p">,</span> <span class="n">Py</span> <span class="o">=</span> <span class="p">(</span><span class="mi">171267639996301888897655876215740853691</span><span class="p">,</span><span class="mi">17515108248008333086755597522577521623</span><span class="p">)</span>
<span class="n">kPx</span><span class="p">,</span> <span class="n">kPy</span> <span class="o">=</span> <span class="p">(</span><span class="mi">188895340186764942633236645126076288341</span><span class="p">,</span><span class="mi">83479740999426843193232746079655679683</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">Fp</span><span class="p">(</span><span class="n">Fp</span><span class="p">(</span><span class="n">kPx</span><span class="p">)</span> <span class="o">/</span> <span class="n">Fp</span><span class="p">(</span><span class="n">kPy</span><span class="p">))</span> <span class="o">/</span> <span class="n">Fp</span><span class="p">(</span><span class="n">Fp</span><span class="p">(</span><span class="n">Px</span><span class="p">)</span> <span class="o">/</span> <span class="n">Fp</span><span class="p">(</span><span class="n">Py</span><span class="p">))</span>
<span class="n">Qx</span><span class="p">,</span> <span class="n">Qy</span> <span class="o">=</span> <span class="p">(</span><span class="mi">297852081644256946433151544727117912742</span><span class="p">,</span><span class="mi">290511976119282973548634325709079145116</span><span class="p">)</span>
<span class="n">lQx</span><span class="p">,</span> <span class="n">lQy</span> <span class="o">=</span> <span class="p">(</span><span class="mi">83612230453021831094477443040279571268</span><span class="p">,</span><span class="mi">430089842202788608377537684275601116540</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">Fq</span><span class="p">(</span><span class="n">Fq</span><span class="p">(</span><span class="n">lQx</span><span class="p">)</span> <span class="o">/</span> <span class="n">Fq</span><span class="p">(</span><span class="n">lQy</span><span class="p">))</span> <span class="o">/</span> <span class="n">Fq</span><span class="p">(</span><span class="n">Fq</span><span class="p">(</span><span class="n">Qx</span><span class="p">)</span> <span class="o">/</span> <span class="n">Fq</span><span class="p">(</span><span class="n">Qy</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s">, </span><span class="si">{</span><span class="n">l</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<p>However, these primes aren’t special (re: the flag), so maybe this also isn’t intended?</p>
<h2 id="elegant-curve">ELEGANT CURVE</h2>
<h3 id="challenge-1">Challenge</h3>
<blockquote>
<p>Playing with <a href="https://cr.yp.toc.tf/tasks/elegant_curve_ae8c3f188723d2852c9f939ba87d930398720a62.txz">Fire</a>!</p>
<p><code class="language-plaintext highlighter-rouge">nc 07.cr.yp.toc.tf 10010</code></p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">def</span> <span class="nf">tonelli_shanks</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="n">q</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">q</span> <span class="o">//</span> <span class="mi">2</span>
<span class="n">s</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">if</span> <span class="n">s</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">r1</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">4</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
<span class="n">r2</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">r1</span>
<span class="k">return</span> <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">z</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="n">q</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">z</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">r</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">int</span><span class="p">((</span><span class="n">q</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">q</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">s</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="n">t</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">r1</span> <span class="o">=</span> <span class="n">r</span>
<span class="n">r2</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">r1</span>
<span class="k">return</span> <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">pow</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="mi">2</span><span class="o">**</span><span class="n">i</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">b</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mi">2</span><span class="o">**</span><span class="p">(</span><span class="n">m</span><span class="o">-</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">r</span> <span class="o">*</span> <span class="n">b</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">t</span> <span class="o">*</span> <span class="n">b</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">b</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">i</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
<span class="k">if</span> <span class="n">A</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">B</span>
<span class="k">if</span> <span class="n">B</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">A</span>
<span class="n">l</span> <span class="o">=</span> <span class="p">((</span><span class="n">B</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="n">B</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">A</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">l</span><span class="o">*</span><span class="n">l</span> <span class="o">-</span> <span class="n">A</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">B</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="n">l</span><span class="o">*</span><span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">x</span><span class="p">)</span> <span class="o">-</span> <span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">y</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">double</span><span class="p">(</span><span class="n">G</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
<span class="k">if</span> <span class="n">G</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">G</span>
<span class="n">l</span> <span class="o">=</span> <span class="p">((</span><span class="mi">3</span><span class="o">*</span><span class="n">G</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">G</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">a</span><span class="p">)</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">G</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">l</span><span class="o">*</span><span class="n">l</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">G</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="n">l</span><span class="o">*</span><span class="p">(</span><span class="n">G</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">x</span><span class="p">)</span> <span class="o">-</span> <span class="n">G</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">y</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">multiply</span><span class="p">(</span><span class="n">point</span><span class="p">,</span> <span class="n">exponent</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
<span class="n">r0</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">r1</span> <span class="o">=</span> <span class="n">point</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">bin</span><span class="p">(</span><span class="n">exponent</span><span class="p">)[</span><span class="mi">2</span><span class="p">:]:</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="s">'0'</span><span class="p">:</span>
<span class="n">r1</span> <span class="o">=</span> <span class="n">add</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span> <span class="n">r1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">r0</span> <span class="o">=</span> <span class="n">double</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">r0</span> <span class="o">=</span> <span class="n">add</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span> <span class="n">r1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">r1</span> <span class="o">=</span> <span class="n">double</span><span class="p">(</span><span class="n">r1</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">return</span> <span class="n">r0</span>
<span class="k">def</span> <span class="nf">random_point</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">y</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">tonelli_shanks</span><span class="p">((</span><span class="n">x</span><span class="o">**</span><span class="mi">3</span> <span class="o">+</span> <span class="n">a</span><span class="o">*</span><span class="n">x</span> <span class="o">+</span> <span class="n">b</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">continue</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" hi talented cryptographers, the mission is decrypt a secret message"</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" with given parameters for two elliptic curve, so be genius and send"</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" suitable parameters, now try to get the flag! "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">nbit</span> <span class="o">=</span> <span class="mi">160</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[S]end ECC parameters and solve the task </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'s'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Send the parameters of first ECC y^2 = x^3 + ax + b like: a, b, p "</span><span class="p">)</span>
<span class="n">params</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="n">params</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">b</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your parameters are not valid!!"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o"><</span> <span class="n">a</span> <span class="o"><</span> <span class="n">p</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o"><</span> <span class="n">b</span> <span class="o"><</span> <span class="n">p</span> <span class="ow">and</span> <span class="n">p</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">==</span> <span class="n">nbit</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Send the parameters of second ECC y^2 = x^3 + cx + d like: c, d, q "</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| such that 0 < q - p <= 2022"</span><span class="p">)</span>
<span class="n">params</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="n">params</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)</span>
<span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">q</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">c</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">d</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your parameters are not valid!!"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">q</span><span class="p">)</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o"><</span> <span class="n">c</span> <span class="o"><</span> <span class="n">q</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o"><</span> <span class="n">d</span> <span class="o"><</span> <span class="n">q</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o"><</span> <span class="n">q</span> <span class="o">-</span> <span class="n">p</span> <span class="o"><=</span> <span class="mi">2022</span> <span class="ow">and</span> <span class="n">q</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o">==</span> <span class="n">nbit</span><span class="p">:</span>
<span class="n">G</span><span class="p">,</span> <span class="n">H</span> <span class="o">=</span> <span class="n">random_point</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">),</span> <span class="n">random_point</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">q</span><span class="p">)</span>
<span class="n">r</span><span class="p">,</span> <span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">)]</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">"| G is on first ECC and G ="</span><span class="p">,</span> <span class="p">{</span><span class="n">G</span><span class="p">})</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">"| H is on second ECC and H ="</span><span class="p">,</span> <span class="p">{</span><span class="n">H</span><span class="p">})</span>
<span class="n">U</span> <span class="o">=</span> <span class="n">multiply</span><span class="p">(</span><span class="n">G</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">V</span> <span class="o">=</span> <span class="n">multiply</span><span class="p">(</span><span class="n">H</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">q</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">"| r * G ="</span><span class="p">,</span> <span class="p">{</span><span class="n">U</span><span class="p">})</span>
<span class="n">pr</span><span class="p">(</span><span class="sa">f</span><span class="s">"| s * H ="</span><span class="p">,</span> <span class="p">{</span><span class="n">V</span><span class="p">})</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Send r, s to get the flag: "</span><span class="p">)</span>
<span class="n">rs</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">rs</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">u</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| invalid input, bye!"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">u</span> <span class="o">==</span> <span class="n">r</span> <span class="ow">and</span> <span class="n">v</span> <span class="o">==</span> <span class="n">s</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| You got the flag:"</span><span class="p">,</span> <span class="n">flag</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| the answer is not correct, bye!"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| invalid parameters, bye!"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| invalid parameters, bye!"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<p>The challenge is to supply two elliptic curves</p>
\[E_p: y^2 = x^3 + ax + b \pmod p \\
E_p: y^2 = x^3 + cx + d \pmod q\]
<p>Where $0 < q - p < 2023$ and $0 < a,b < p$, $0 < c,d < q$.</p>
<p>Supplying these curves, you are given two pairs of points and the challenge is to solve this discrete log for both pairs. Supplying the two private keys to the server gives the flag.</p>
<h3 id="solution-1">Solution</h3>
<p>This challenge I solved in an identical way to <a href="#tiny-ecc">Tiny ECC</a>. I generated an anomalpus curve $E_p$ and then used <code class="language-plaintext highlighter-rouge">q = next_prime(p)</code>. I then searched for a pair $(c,d)$ where $\#E_q$ was smooth. I think the intended solution was to generate two singular elliptic curves with smooth primes $p,q$ so you could solve the discrete log in $F_p^{\star}$ , but seeing as the last solution worked, this was already in my mind.</p>
<p>First I needed an anomalous curve with 160 bit prime. Luckily, this is in the paper <a href="http://www.monnerat.info/publications/anomalous.pdf">Generating Anomalous Elliptic Curves</a> as an example, so I can use their $m$ value.</p>
<p>Iterating over $c,d$ I found a curve</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">q</span> <span class="o">=</span> <span class="mi">730750818665451459112596905638433048232067472077</span>
<span class="n">aq</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">bq</span> <span class="o">=</span> <span class="mi">481</span>
<span class="n">Eq</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">[</span><span class="n">aq</span><span class="p">,</span><span class="n">bq</span><span class="p">])</span>
<span class="n">factor</span><span class="p">(</span><span class="n">Eq</span><span class="p">.</span><span class="n">order</span><span class="p">())</span>
<span class="mi">2</span><span class="o">^</span><span class="mi">2</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">167</span> <span class="o">*</span> <span class="mi">193</span> <span class="o">*</span> <span class="mi">4129</span> <span class="o">*</span> <span class="mi">882433</span> <span class="o">*</span> <span class="mi">2826107</span> <span class="o">*</span> <span class="mi">51725111</span> <span class="o">*</span> <span class="mi">332577589</span> <span class="o">*</span> <span class="mi">10666075363</span>
</code></pre></div></div>
<p>Which is smooth, with a 34 bit integer as the largest factor.</p>
<p>Sending to the server:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">p</span> <span class="o">=</span> <span class="mi">730750818665451459112596905638433048232067471723</span>
<span class="n">ap</span> <span class="o">=</span> <span class="mi">425706413842211054102700238164133538302169176474</span>
<span class="n">bp</span> <span class="o">=</span> <span class="mi">203362936548826936673264444982866339953265530166</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">730750818665451459112596905638433048232067472077</span>
<span class="n">aq</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">bq</span> <span class="o">=</span> <span class="mi">481</span>
</code></pre></div></div>
<p>I get my two pairs of points I can easily solve the dlog for</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">getrandbits</span>
<span class="c1"># params from http://www.monnerat.info/publications/anomalous.pdf
</span><span class="n">D</span> <span class="o">=</span> <span class="mi">11</span>
<span class="n">j</span> <span class="o">=</span> <span class="o">-</span><span class="mi">2</span><span class="o">**</span><span class="mi">15</span>
<span class="k">def</span> <span class="nf">anom_curve</span><span class="p">():</span>
<span class="n">m</span> <span class="o">=</span> <span class="mi">257743850762632419871495</span>
<span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="mi">11</span><span class="o">*</span><span class="n">m</span><span class="o">*</span><span class="p">(</span><span class="n">m</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">+</span> <span class="mi">3</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="o">*</span><span class="n">j</span> <span class="o">*</span> <span class="n">inverse_mod</span><span class="p">((</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1728</span><span class="p">),</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">j</span> <span class="o">*</span> <span class="n">inverse_mod</span><span class="p">((</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1728</span><span class="p">),</span> <span class="n">p</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">E</span><span class="p">.</span><span class="n">gens</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="n">p</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">E</span><span class="p">,</span> <span class="n">G</span>
<span class="k">def</span> <span class="nf">SmartAttack</span><span class="p">(</span><span class="n">P</span><span class="p">,</span><span class="n">Q</span><span class="p">,</span><span class="n">p</span><span class="p">):</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">P</span><span class="p">.</span><span class="n">curve</span><span class="p">()</span>
<span class="n">Eqp</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Qp</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">[</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">+</span> <span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">p</span><span class="p">)</span><span class="o">*</span><span class="n">p</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">E</span><span class="p">.</span><span class="n">a_invariants</span><span class="p">()</span> <span class="p">])</span>
<span class="n">P_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">P_Qp</span> <span class="ow">in</span> <span class="n">P_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">P_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">Q_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">Q_Qp</span> <span class="ow">in</span> <span class="n">Q_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">Q_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">p_times_P</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">P_Qp</span>
<span class="n">p_times_Q</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">Q_Qp</span>
<span class="n">x_P</span><span class="p">,</span><span class="n">y_P</span> <span class="o">=</span> <span class="n">p_times_P</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">x_Q</span><span class="p">,</span><span class="n">y_Q</span> <span class="o">=</span> <span class="n">p_times_Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">phi_P</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_P</span><span class="o">/</span><span class="n">y_P</span><span class="p">)</span>
<span class="n">phi_Q</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_Q</span><span class="o">/</span><span class="n">y_Q</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">phi_Q</span><span class="o">/</span><span class="n">phi_P</span>
<span class="k">return</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">730750818665451459112596905638433048232067471723</span>
<span class="n">ap</span> <span class="o">=</span> <span class="mi">425706413842211054102700238164133538302169176474</span>
<span class="n">bp</span> <span class="o">=</span> <span class="mi">203362936548826936673264444982866339953265530166</span>
<span class="n">Ep</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="n">ap</span><span class="p">,</span><span class="n">bp</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">126552689249226752349356206494226396414163660811</span><span class="p">,</span> <span class="mi">559777835342379827315577715664975494598512818777</span><span class="p">)</span>
<span class="n">rG</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">190128385937465835164338802317889165657442536853</span><span class="p">,</span> <span class="mi">604514027124204305317929024826237325074492980218</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">SmartAttack</span><span class="p">(</span><span class="n">G</span><span class="p">,</span><span class="n">rG</span><span class="p">,</span><span class="n">p</span><span class="p">))</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">730750818665451459112596905638433048232067472077</span>
<span class="n">aq</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">bq</span> <span class="o">=</span> <span class="mi">481</span>
<span class="n">Eq</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">[</span><span class="n">aq</span><span class="p">,</span><span class="n">bq</span><span class="p">])</span>
<span class="n">H</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">284866865619833057500909264169831974815120720320</span><span class="p">,</span> <span class="mi">612322665682105897045018564282609259776516527853</span><span class="p">)</span>
<span class="n">sH</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">673590124165798818844330235458561515292416807353</span><span class="p">,</span> <span class="mi">258709088293250578320930080839442511989120686226</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">H</span><span class="p">.</span><span class="n">discrete_log</span><span class="p">(</span><span class="n">sH</span><span class="p">))</span>
</code></pre></div></div>
<p>Sending the two keys, I get the flag</p>
<h5 id="flag-1">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{Pl4yIn9_Wi7H_ECC_1Z_liK3_pLAiNg_wiTh_Fir3!!}</code></p>
<h2 id="double-miff">Double Miff</h2>
<h3 id="challenge-2">Challenge</h3>
<blockquote>
<p>A new approach, a new attack. Can you attack this curve?
<a href="https://cr.yp.toc.tf/tasks/double_miff_58336b2ad5ed82754ac8e9b3bdcc8f25623c909c.txz">double_miff.txz</a></p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">Q</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="k">def</span> <span class="nf">onmiff</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">G</span><span class="p">):</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">G</span>
<span class="k">return</span> <span class="p">(</span><span class="n">a</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="p">(</span><span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">-</span> <span class="n">b</span><span class="o">*</span><span class="n">y</span><span class="o">*</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">addmiff</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">Y</span><span class="p">):</span>
<span class="n">x_1</span><span class="p">,</span> <span class="n">y_1</span> <span class="o">=</span> <span class="n">X</span>
<span class="n">x_2</span><span class="p">,</span> <span class="n">y_2</span> <span class="o">=</span> <span class="n">Y</span>
<span class="n">x_3</span> <span class="o">=</span> <span class="p">(</span><span class="n">x_1</span> <span class="o">+</span> <span class="n">x_2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y_1</span><span class="o">*</span><span class="n">y_2</span><span class="p">)</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">((</span><span class="mi">1</span> <span class="o">+</span> <span class="n">x_1</span><span class="o">*</span><span class="n">x_2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">y_1</span><span class="o">*</span><span class="n">y_2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">y_3</span> <span class="o">=</span> <span class="p">(</span><span class="n">y_1</span> <span class="o">+</span> <span class="n">y_2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">x_1</span><span class="o">*</span><span class="n">x_2</span><span class="p">)</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">((</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y_1</span><span class="o">*</span><span class="n">y_2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">x_1</span><span class="o">*</span><span class="n">x_2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x_3</span><span class="p">,</span> <span class="n">y_3</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
<span class="n">m1</span><span class="p">,</span> <span class="n">m2</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">flag</span><span class="p">[:</span><span class="n">l</span><span class="p">]),</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="n">l</span><span class="p">:])</span>
<span class="k">assert</span> <span class="n">m1</span> <span class="o"><</span> <span class="p">(</span><span class="n">p</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span> <span class="ow">and</span> <span class="n">m2</span> <span class="o"><</span> <span class="p">(</span><span class="n">p</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">onmiff</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span> <span class="ow">and</span> <span class="n">onmiff</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">Q</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">P</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">m1</span> <span class="ow">and</span> <span class="n">Q</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">m2</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'P + Q = </span><span class="si">{</span><span class="n">addmiff</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">Q</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Q + Q = </span><span class="si">{</span><span class="n">addmiff</span><span class="p">(</span><span class="n">Q</span><span class="p">,</span> <span class="n">Q</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'P + P = </span><span class="si">{</span><span class="n">addmiff</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">P</span> <span class="o">+</span> <span class="n">Q</span> <span class="o">=</span> <span class="p">(</span><span class="mi">540660810777215925744546848899656347269220877882</span><span class="p">,</span> <span class="mi">102385886258464739091823423239617164469644309399</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">+</span> <span class="n">Q</span> <span class="o">=</span> <span class="p">(</span><span class="mi">814107817937473043563607662608397956822280643025</span><span class="p">,</span> <span class="mi">961531436304505096581595159128436662629537620355</span><span class="p">)</span>
<span class="n">P</span> <span class="o">+</span> <span class="n">P</span> <span class="o">=</span> <span class="p">(</span><span class="mi">5565164868721370436896101492497307801898270333</span><span class="p">,</span> <span class="mi">496921328106062528508026412328171886461223562143</span><span class="p">)</span>
</code></pre></div></div>
<h3 id="solution-2">Solution</h3>
<p>We have a curve equation $ax(y^2 - 1) \equiv by(x^2 - 1) \mod p$ with unknown $a$, $b$, $p$; $P$ and $Q$ are some points on it, and we have $P + Q$, $Q + Q$ and $P + P$.</p>
<p>We need to recover $x$-coordinates of $P$ and $Q$, since they contain parts of the flag.
Addition here is commutative and associative, so we have</p>
\[(P + P) + (Q + Q) = P + P + Q + Q = P + Q + P + Q = (P + Q) + (P + Q).\]
<p>We have 2 ways of representing $x$- and $y$-coordinates of $P + P + Q + Q$. Set $P + Q = (x_1, y_1)$, $Q + Q = (x_2, y_2)$, $P + P = (x_3, y_3)$, $P + P + Q + Q = (x_0, y_0)$. Then from addition formulas for $x$ we have</p>
<p>\(x_0 \equiv \frac{(x_2+x_3)(1+y_2y_3)}{(1+x_2x_3)(1-y_2y_3)} \mod p \\
x_0 \equiv \frac{2x_1(1+y_1^2)}{(1+x_1^2)(1-y_1^2)} \mod p\),</p>
<p>from where we get this:</p>
\[p|((1+x_1^2)(1-y_1^2)(x_2+x_3)(1+y_2y_3) - 2x_1(1+y_1^2)(1+x_2x_3)(1-y_2y_3))\]
<p>Analogously from addition formulas for y we get</p>
\[p|((1+y_1^2)(1-x_1^2)(y_2+y_3)(1+x_2x_3)-2y_1(1+x_1^2)(1+y_2y_3)(1-x_2x_3))\]
<p>We can compute gcd of 2 numbers above to get a small multiple of $p$ ($8p$ in this case), and from there we get $p = 1141623079614587900848768080393294899678477852887$.</p>
<p>Recall that for any point on the curve we have $ax(y^2-1) \equiv by(x^2-1) \mod p$, from where we can compute $k \equiv \frac{a}{b} \equiv \frac{y(x^2 - 1)}{x(y^2-1)} \mod p$ by using any known point.</p>
<p>Note that we also have $\frac{y}{y^2-1} \equiv k\frac{x}{x^2-1} \mod p$.</p>
<p>Set $P = (x_4, y_4)$, and from addition formulas we get:</p>
\[x_3 \equiv \frac{2x_4(1+y_4^2)}{(1+x_4^2)(1-y_4^2)} \mod p \\
y_3 \equiv \frac{2y_4(1+x_4^2)}{(1+y_4^2)(1-x_4^2)} \mod p\]
<p>from where we get</p>
\[x_3y_3 \equiv \frac{4x_4y_4}{(x_4^2-1)(y_4^2-1)} \equiv 4k(\frac{x_4}{x_4^2 - 1})^2 \mod p\]
<p>and then $(\frac{x_4^2-1}{x_4})^2 \equiv \frac{4k}{x_3y_3} \mod p$ and have $\frac{x_4^2-1}{x_4} \equiv \pm l \mod p$, where $l \equiv (\frac{4k}{x_3y_3})^{\frac{p+1}{4}} \mod p$, since $p \equiv 3 \mod 4$.</p>
<p>From here we get $x_4^2 \mp lx_4 - 1 \equiv 0 \mod p$. Discriminant in both cases is equal to $D \equiv l^2 + 4 \mod p$, and we get roots of both equations with $\frac{\pm l \pm \sqrt{D}}{2} \mod p$. Check each one of them, the one that results into printable text gives us the first half of the flag. Analogously we can recover $x$-coordinate of $Q$ and get second half of the flag. By concatenating them, we will have the full flag. Judging by the flag, though, this may be an unintended solution.</p>
<h3 id="implementation">Implementation</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">isPrime</span><span class="p">,</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="n">x1</span><span class="p">,</span> <span class="n">y1</span> <span class="o">=</span> <span class="p">(</span><span class="mi">540660810777215925744546848899656347269220877882</span><span class="p">,</span> <span class="mi">102385886258464739091823423239617164469644309399</span><span class="p">)</span>
<span class="n">x2</span><span class="p">,</span> <span class="n">y2</span> <span class="o">=</span> <span class="p">(</span><span class="mi">814107817937473043563607662608397956822280643025</span><span class="p">,</span> <span class="mi">961531436304505096581595159128436662629537620355</span><span class="p">)</span>
<span class="n">x3</span><span class="p">,</span> <span class="n">y3</span> <span class="o">=</span> <span class="p">(</span><span class="mi">5565164868721370436896101492497307801898270333</span><span class="p">,</span> <span class="mi">496921328106062528508026412328171886461223562143</span><span class="p">)</span>
<span class="n">num1</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">x1</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">y1</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">x2</span> <span class="o">+</span> <span class="n">x3</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y2</span> <span class="o">*</span> <span class="n">y3</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">x1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y1</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">x2</span> <span class="o">*</span> <span class="n">x3</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">y2</span> <span class="o">*</span> <span class="n">y3</span><span class="p">)</span>
<span class="n">num2</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y1</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">x1</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">y2</span> <span class="o">+</span> <span class="n">y3</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">x2</span> <span class="o">*</span> <span class="n">x3</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">y1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">x1</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y2</span> <span class="o">*</span> <span class="n">y3</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">x2</span> <span class="o">*</span> <span class="n">x3</span><span class="p">)</span>
<span class="n">pmult</span> <span class="o">=</span> <span class="n">gcd</span><span class="p">(</span><span class="n">num1</span><span class="p">,</span> <span class="n">num2</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">10</span><span class="p">):</span>
<span class="k">while</span> <span class="n">pmult</span> <span class="o">%</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">pmult</span> <span class="o">//=</span> <span class="n">i</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">pmult</span><span class="p">):</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">pmult</span>
<span class="k">break</span>
<span class="k">def</span> <span class="nf">recover_half</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">y</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="p">(</span><span class="n">y</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">),</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">4</span> <span class="o">*</span> <span class="n">k</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="n">y</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">),</span> <span class="p">(</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="mi">4</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="n">D</span> <span class="o">=</span> <span class="p">(</span><span class="n">l</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">sqrtD</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="p">(</span><span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="mi">4</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span>
<span class="n">num</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">*</span> <span class="n">l</span> <span class="o">+</span> <span class="n">j</span> <span class="o">*</span> <span class="n">sqrtD</span><span class="p">)</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">num</span><span class="p">)</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">'CCTF{'</span> <span class="ow">in</span> <span class="n">text</span> <span class="ow">or</span> <span class="sa">b</span><span class="s">'}'</span> <span class="ow">in</span> <span class="n">text</span><span class="p">:</span>
<span class="k">return</span> <span class="n">text</span>
<span class="n">first_half</span> <span class="o">=</span> <span class="n">recover_half</span><span class="p">(</span><span class="n">x3</span><span class="p">,</span> <span class="n">y3</span><span class="p">)</span>
<span class="n">second_half</span> <span class="o">=</span> <span class="n">recover_half</span><span class="p">(</span><span class="n">x2</span><span class="p">,</span> <span class="n">y2</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="p">(</span><span class="n">first_half</span> <span class="o">+</span> <span class="n">second_half</span><span class="p">).</span><span class="n">decode</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</code></pre></div></div>
<h5 id="flag-2">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{D39enEr47E_ECC_4TtaCk!_iN_Huffs?}</code></p>
<h2 id="ecchimera">Ecchimera</h2>
<h3 id="challenge-3">Challenge</h3>
<blockquote>
<p>The <a href="https://cryp.toc.tf/tasks/ecchimera_da57494454cba7683105130b6161f4f65c41306f.txz">mixed</a> version is a hard version!</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">43216667049953267964807040003094883441902922285265979216983383601881964164181</span>
<span class="n">U</span> <span class="o">=</span> <span class="mi">18230294945466842193029464818176109628473414458693455272527849780121431872221</span>
<span class="n">V</span> <span class="o">=</span> <span class="mi">13100009444194791894141652184719316024656527520759416974806280188465496030062</span>
<span class="n">W</span> <span class="o">=</span> <span class="mi">5543957019331266247602346710470760261172306141315670694208966786894467019982</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">flag</span><span class="p">.</span><span class="n">lstrip</span><span class="p">(</span><span class="sa">b</span><span class="s">'CCTF{'</span><span class="p">).</span><span class="n">rstrip</span><span class="p">(</span><span class="sa">b</span><span class="s">'}'</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">flag</span><span class="p">.</span><span class="nb">hex</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">s</span> <span class="o"><</span> <span class="n">n</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">U</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">W</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'G = </span><span class="si">{</span><span class="n">G</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'s * G = </span><span class="si">{</span><span class="n">s</span> <span class="o">*</span> <span class="n">G</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<p>We have an elliptic curve defined over the ring of integers modulo n, or $Z_n$. Generally elliptic curves are defined over a field with a prime $p$, or $F_p$, but in this case we working with the ring $Z_n$.</p>
<p>The rest of the question is a typical ECDLP (Elliptic Curve Discrete Log Problem) problem, where we’re given a generator point $G$ on the curve and the point $s * G$, where $s$ is our flag and the value we need to solve for.</p>
<p>Because $n$ isn’t prime, we need to take a different approach to solve the discrete log problem. If we use <a href="http://factordb.com/index.php?query=43216667049953267964807040003094883441902922285265979216983383601881964164181">factordb</a>, we can factor $n$ into 2 primes $p$ and $q$.</p>
<p>According to this link https://link.springer.com/content/pdf/10.1007%2FBFb0054116.pdf (pg. 4), the number of points on the elliptic curve ($\#E_{Z_n}$) is equivalent to the product of the order of the curve defined over $F_p$ and $F_q$. In other words,</p>
\[\#E_{Z_n} = \#E_{F_p} * \#E_{F_q}\]
<p>Now because $p$ and $q$ are prime, it’s very simple to figure out $\#E_{F_p}$ and $\#E_{F_q}$, we can do it directly in Sage</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">43216667049953267964807040003094883441902922285265979216983383601881964164181</span>
<span class="n">U</span> <span class="o">=</span> <span class="mi">18230294945466842193029464818176109628473414458693455272527849780121431872221</span>
<span class="n">V</span> <span class="o">=</span> <span class="mi">13100009444194791894141652184719316024656527520759416974806280188465496030062</span>
<span class="n">W</span> <span class="o">=</span> <span class="mi">5543957019331266247602346710470760261172306141315670694208966786894467019982</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">U</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">W</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">sG</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">190116434441822299465355144611018694747</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">227316839687407660649258155239617355023</span>
<span class="k">assert</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span> <span class="o">==</span> <span class="n">n</span>
<span class="c1"># P and Q curves
</span><span class="n">Ep</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">U</span> <span class="o">%</span> <span class="n">p</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">V</span> <span class="o">%</span> <span class="n">p</span><span class="p">),</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">W</span> <span class="o">%</span> <span class="n">p</span><span class="p">)])</span>
<span class="n">Eq</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">U</span> <span class="o">%</span> <span class="n">q</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">V</span> <span class="o">%</span> <span class="n">q</span><span class="p">),</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">W</span> <span class="o">%</span> <span class="n">q</span><span class="p">)])</span>
<span class="n">kp</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">.</span><span class="n">order</span><span class="p">()</span>
<span class="n">kq</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">.</span><span class="n">order</span><span class="p">()</span>
</code></pre></div></div>
<p>Now in order to solve the discrete log on the curve over the ring $Z_n$, what we can do instead is solve the discrete log on the curve over the field $F_p$ and $F_q$ and then combine the results using the Chinese remainder theorem (from pg.11 of the same paper linked above). Another explanation is given here: https://crypto.stackexchange.com/questions/72613/elliptic-curve-discrete-log-in-a-composite-ring.</p>
<p>If we look at the order of the curve over $F_p$ and $F_q$ we notice a few things.</p>
\[\#E_{F_p} = p = 190116434441822299465355144611018694747 \\
\#E_{F_q} = 2^4 * 3 * 13 * 233 * 4253 * 49555349 * 7418313402470596923151\]
<p>If the order of a curve defined over a field $F_p$ is equal to $p$, then that means the curve is anomalous, and there’s an attack (called Smart’s attack) that we can apply to solve the discrete log easily. So we can apply this to the curve defined over $F_p$. This also implies that every point generated by the curve also has an order of $p$.</p>
<p>For the other curve defined over $F_q$, notice that the order is somewhat smooth, meaning that the number can be decomposed into small-ish primes. Other than the last prime factor, the other numbers are fairly small primes. This kind of smooth order implies the Pohlig Hellman attack, where we solve the discrete log problem by solving the discrete log over the subgroups of the group generated by the point $G$.</p>
<p>To summarize, we have a elliptic curve defined over $Z_n$ and we need to solve the discrete log problem to find a value $s$ given $G$ and $sG$. We can split the curve into 2 curves defined over $F_p$ and $F_q$. Then we solve the discrete log over these 2 curves for $s_p$ and $s_q$ such that</p>
\[s_p \equiv s \mod \#E_{F_p} \\
s_q \equiv s \mod \#E_{F_q}\]
<p>Using the Chinese remainder theorem we combine these results to find</p>
\[s \mod \\#E_{Z_n}\]
<p>because</p>
\[\#E_{Z_n} = \#E_{F_p} * \#E_{F_q}\]
<h4 id="pohlig-hellman">Pohlig Hellman</h4>
<p>We’ll start with the curve defined over $F_q$. First we find the order of the point $G$ defined on the curve:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">43216667049953267964807040003094883441902922285265979216983383601881964164181</span>
<span class="n">U</span> <span class="o">=</span> <span class="mi">18230294945466842193029464818176109628473414458693455272527849780121431872221</span>
<span class="n">V</span> <span class="o">=</span> <span class="mi">13100009444194791894141652184719316024656527520759416974806280188465496030062</span>
<span class="n">W</span> <span class="o">=</span> <span class="mi">5543957019331266247602346710470760261172306141315670694208966786894467019982</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">U</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">W</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">sG</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">190116434441822299465355144611018694747</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">227316839687407660649258155239617355023</span>
<span class="k">assert</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span> <span class="o">==</span> <span class="n">n</span>
<span class="c1"># P curve
</span><span class="n">Eq</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">U</span> <span class="o">%</span> <span class="n">q</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">V</span> <span class="o">%</span> <span class="n">q</span><span class="p">),</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">W</span> <span class="o">%</span> <span class="n">q</span><span class="p">)])</span>
<span class="n">kq</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">.</span><span class="n">order</span><span class="p">()</span>
<span class="n">Gq</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">sGq</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">Gq</span><span class="p">.</span><span class="n">order</span><span class="p">())</span>
</code></pre></div></div>
<p>Output is</p>
\[75772279895802553549752718413205785008 = 2^4 * 13 * 233 * 4253 * 49555349 * 7418313402470596923151\]
<p>Other than the last factor, the number is fairly smooth. Also notice that the order of $G$ isn’t equal to the order of the curve $\#E_{F_q}$ (there’s a factor of 3 missing).</p>
<p>We will run the Pohlig Hellman algorithm using every factor except the last one, because solving the discrete log in that prime-order subgroup will take too long. If $s_q$ is small enough, we don’t have use the last prime and we will still find the correct value.</p>
<p>Code below is to find $s_q$</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">primes</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="o">^</span><span class="mi">4</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">233</span><span class="p">,</span> <span class="mi">4253</span><span class="p">,</span> <span class="mi">49555349</span><span class="p">,</span> <span class="mi">7418313402470596923151</span><span class="p">]</span> <span class="c1">#don't use 3 and last one
</span><span class="n">dlogs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">fac</span> <span class="ow">in</span> <span class="n">primes</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">t</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">Gq</span><span class="p">.</span><span class="n">order</span><span class="p">())</span> <span class="o">//</span> <span class="nb">int</span><span class="p">(</span><span class="n">fac</span><span class="p">)</span>
<span class="n">dlog</span> <span class="o">=</span> <span class="p">(</span><span class="n">t</span><span class="o">*</span><span class="n">Gq</span><span class="p">).</span><span class="n">discrete_log</span><span class="p">(</span><span class="n">t</span><span class="o">*</span><span class="n">sGq</span><span class="p">)</span> <span class="c1">#discrete_log(t*sGq, t*Gq, operation="+")
</span> <span class="n">dlogs</span> <span class="o">+=</span> <span class="p">[</span><span class="n">dlog</span><span class="p">]</span>
<span class="c1">#print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
</span>
<span class="n">q_secret</span> <span class="o">=</span> <span class="n">crt</span><span class="p">(</span><span class="n">dlogs</span><span class="p">,</span> <span class="n">primes</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>
<p>Running this we get $s_q = 9092500866606561$.</p>
<h4 id="smarts-attack">Smart’s attack</h4>
<p>Onto the other curve. We know the order of the curve equals the prime $p$ (anomalous curve), so we can apply Smart’s attack to solve the discrete log quickly.</p>
<p>Code to apply this attack and solve for $s_p$ is below:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">n</span> <span class="o">=</span> <span class="mi">43216667049953267964807040003094883441902922285265979216983383601881964164181</span>
<span class="n">U</span> <span class="o">=</span> <span class="mi">18230294945466842193029464818176109628473414458693455272527849780121431872221</span>
<span class="n">V</span> <span class="o">=</span> <span class="mi">13100009444194791894141652184719316024656527520759416974806280188465496030062</span>
<span class="n">W</span> <span class="o">=</span> <span class="mi">5543957019331266247602346710470760261172306141315670694208966786894467019982</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">U</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">W</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">sG</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">190116434441822299465355144611018694747</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">227316839687407660649258155239617355023</span>
<span class="k">assert</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span> <span class="o">==</span> <span class="n">n</span>
<span class="c1"># P curve
</span><span class="n">Ep</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">U</span> <span class="o">%</span> <span class="n">p</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">V</span> <span class="o">%</span> <span class="n">p</span><span class="p">),</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">W</span> <span class="o">%</span> <span class="n">p</span><span class="p">)])</span>
<span class="n">kp</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">.</span><span class="n">order</span><span class="p">()</span>
<span class="n">Gp</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">sGp</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">Gp</span><span class="p">.</span><span class="n">order</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">SmartAttack</span><span class="p">(</span><span class="n">P</span><span class="p">,</span><span class="n">Q</span><span class="p">,</span><span class="n">p</span><span class="p">):</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">P</span><span class="p">.</span><span class="n">curve</span><span class="p">()</span>
<span class="n">Eqp</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Qp</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">[</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">+</span> <span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">p</span><span class="p">)</span><span class="o">*</span><span class="n">p</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">E</span><span class="p">.</span><span class="n">a_invariants</span><span class="p">()</span> <span class="p">])</span>
<span class="n">P_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">P_Qp</span> <span class="ow">in</span> <span class="n">P_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">P_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">Q_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">Q_Qp</span> <span class="ow">in</span> <span class="n">Q_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">Q_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">p_times_P</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">P_Qp</span>
<span class="n">p_times_Q</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">Q_Qp</span>
<span class="n">x_P</span><span class="p">,</span><span class="n">y_P</span> <span class="o">=</span> <span class="n">p_times_P</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">x_Q</span><span class="p">,</span><span class="n">y_Q</span> <span class="o">=</span> <span class="n">p_times_Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">phi_P</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_P</span><span class="o">/</span><span class="n">y_P</span><span class="p">)</span>
<span class="n">phi_Q</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_Q</span><span class="o">/</span><span class="n">y_Q</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">phi_Q</span><span class="o">/</span><span class="n">phi_P</span>
<span class="k">return</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="n">p_secret</span> <span class="o">=</span> <span class="n">SmartAttack</span><span class="p">(</span><span class="n">Gp</span><span class="p">,</span><span class="n">sGp</span><span class="p">,</span><span class="n">p</span><span class="p">)</span>
</code></pre></div></div>
<p>Running that code we get $s_p = 35886536999264548257653961517736633452$</p>
<h4 id="crt">CRT</h4>
<p>All that’s left is to combine our 2 answers with CRT and solve for the flag.
Let the order of $G$ on $E_{F_p}$ be $n_p$ and the order of $G$ on $E_{F_q}$ be $n_q$.</p>
<p>Also note that:
\(\#E_{F_p} = n_p\\
\#E_{F_q} = n_q \cdot 3 \cdot 7418313402470596923151\)</p>
<p>We have the following equations:
\(s_p \equiv s \mod n_p\\
s_q \equiv s \mod n_q\)</p>
<p>If the $s$ is small enough, CRT will be able to recover the flag.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">flag</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">crt</span><span class="p">([</span><span class="n">p_secret</span><span class="p">,</span> <span class="n">q_secret</span><span class="p">],</span> <span class="p">[</span><span class="n">Gp</span><span class="p">.</span><span class="n">order</span><span class="p">(),</span> <span class="n">Gq</span><span class="p">.</span><span class="n">order</span><span class="p">()</span> <span class="o">//</span> <span class="mi">7418313402470596923151</span><span class="p">])))</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</code></pre></div></div>
<h3 id="solution-3">Solution</h3>
<p>Full solution code below</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">43216667049953267964807040003094883441902922285265979216983383601881964164181</span>
<span class="n">U</span> <span class="o">=</span> <span class="mi">18230294945466842193029464818176109628473414458693455272527849780121431872221</span>
<span class="n">V</span> <span class="o">=</span> <span class="mi">13100009444194791894141652184719316024656527520759416974806280188465496030062</span>
<span class="n">W</span> <span class="o">=</span> <span class="mi">5543957019331266247602346710470760261172306141315670694208966786894467019982</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">U</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">V</span><span class="p">,</span> <span class="n">W</span><span class="p">])</span>
<span class="n">G</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">sG</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">190116434441822299465355144611018694747</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">227316839687407660649258155239617355023</span>
<span class="k">assert</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span> <span class="o">==</span> <span class="n">n</span>
<span class="c1"># P curve
</span><span class="n">Ep</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">U</span> <span class="o">%</span> <span class="n">p</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">V</span> <span class="o">%</span> <span class="n">p</span><span class="p">),</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">W</span> <span class="o">%</span> <span class="n">p</span><span class="p">)])</span>
<span class="n">Eq</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">GF</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">U</span> <span class="o">%</span> <span class="n">q</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">V</span> <span class="o">%</span> <span class="n">q</span><span class="p">),</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">W</span> <span class="o">%</span> <span class="n">q</span><span class="p">)])</span>
<span class="n">kp</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">.</span><span class="n">order</span><span class="p">()</span>
<span class="n">kq</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">.</span><span class="n">order</span><span class="p">()</span>
<span class="n">Gp</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">Gq</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">6907136022576092896571634972837671088049787669883537619895520267229978111036</span><span class="p">,</span> <span class="mi">35183770197918519490131925119869132666355991678945374923783026655753112300226</span><span class="p">)</span>
<span class="n">sGp</span> <span class="o">=</span> <span class="n">Ep</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="n">sGq</span> <span class="o">=</span> <span class="n">Eq</span><span class="p">(</span><span class="mi">14307615146512108428634858855432876073550684773654843931813155864728883306026</span><span class="p">,</span> <span class="mi">4017273397399838235912099970694615152686460424982458188724369340441833733921</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">Gp</span><span class="p">.</span><span class="n">order</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="n">Gq</span><span class="p">.</span><span class="n">order</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">SmartAttack</span><span class="p">(</span><span class="n">P</span><span class="p">,</span><span class="n">Q</span><span class="p">,</span><span class="n">p</span><span class="p">):</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">P</span><span class="p">.</span><span class="n">curve</span><span class="p">()</span>
<span class="n">Eqp</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">Qp</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">[</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="o">+</span> <span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">p</span><span class="p">)</span><span class="o">*</span><span class="n">p</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">E</span><span class="p">.</span><span class="n">a_invariants</span><span class="p">()</span> <span class="p">])</span>
<span class="n">P_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">P_Qp</span> <span class="ow">in</span> <span class="n">P_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">P_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">P</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">Q_Qps</span> <span class="o">=</span> <span class="n">Eqp</span><span class="p">.</span><span class="n">lift_x</span><span class="p">(</span><span class="n">ZZ</span><span class="p">(</span><span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">all</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">Q_Qp</span> <span class="ow">in</span> <span class="n">Q_Qps</span><span class="p">:</span>
<span class="k">if</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)(</span><span class="n">Q_Qp</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span> <span class="o">==</span> <span class="n">Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">break</span>
<span class="n">p_times_P</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">P_Qp</span>
<span class="n">p_times_Q</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">Q_Qp</span>
<span class="n">x_P</span><span class="p">,</span><span class="n">y_P</span> <span class="o">=</span> <span class="n">p_times_P</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">x_Q</span><span class="p">,</span><span class="n">y_Q</span> <span class="o">=</span> <span class="n">p_times_Q</span><span class="p">.</span><span class="n">xy</span><span class="p">()</span>
<span class="n">phi_P</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_P</span><span class="o">/</span><span class="n">y_P</span><span class="p">)</span>
<span class="n">phi_Q</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">x_Q</span><span class="o">/</span><span class="n">y_Q</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">phi_Q</span><span class="o">/</span><span class="n">phi_P</span>
<span class="k">return</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="n">primes</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="o">^</span><span class="mi">4</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">233</span><span class="p">,</span> <span class="mi">4253</span><span class="p">,</span> <span class="mi">49555349</span><span class="p">,</span> <span class="mi">7418313402470596923151</span><span class="p">]</span> <span class="c1">#don't use 3 and last one
</span><span class="n">dlogs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">fac</span> <span class="ow">in</span> <span class="n">primes</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">t</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">Gq</span><span class="p">.</span><span class="n">order</span><span class="p">())</span> <span class="o">//</span> <span class="nb">int</span><span class="p">(</span><span class="n">fac</span><span class="p">)</span>
<span class="n">dlog</span> <span class="o">=</span> <span class="p">(</span><span class="n">t</span><span class="o">*</span><span class="n">Gq</span><span class="p">).</span><span class="n">discrete_log</span><span class="p">(</span><span class="n">t</span><span class="o">*</span><span class="n">sGq</span><span class="p">)</span> <span class="c1">#discrete_log(t*sGq, t*Gq, operation="+")
</span> <span class="n">dlogs</span> <span class="o">+=</span> <span class="p">[</span><span class="n">dlog</span><span class="p">]</span>
<span class="c1">#print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
</span>
<span class="n">p_secret</span> <span class="o">=</span> <span class="n">SmartAttack</span><span class="p">(</span><span class="n">Gp</span><span class="p">,</span><span class="n">sGp</span><span class="p">,</span><span class="n">p</span><span class="p">)</span>
<span class="n">q_secret</span> <span class="o">=</span> <span class="n">crt</span><span class="p">(</span><span class="n">dlogs</span><span class="p">,</span> <span class="n">primes</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="c1">#Gq.discrete_log(sGq) #9092500866606561 #discrete_log(sGq, Gq, ord=Gq.order(), bounds=2^4 * 3 * 13 * 233 * 4253 * 49555349, operation="+")
</span>
<span class="k">print</span><span class="p">(</span><span class="n">p_secret</span><span class="p">,</span> <span class="n">q_secret</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">crt</span><span class="p">([</span><span class="n">p_secret</span><span class="p">,</span> <span class="n">q_secret</span><span class="p">],</span> <span class="p">[</span><span class="n">Gp</span><span class="p">.</span><span class="n">order</span><span class="p">(),</span> <span class="n">Gq</span><span class="p">.</span><span class="n">order</span><span class="p">()</span> <span class="o">//</span> <span class="mi">7418313402470596923151</span><span class="p">])))</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</code></pre></div></div>
<h5 id="flag-3">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{m1X3d_VeR5!0n_oF_3Cc!}</code></p>
<h2 id="rohald">RoHaLd</h2>
<h3 id="challenge-4">Challenge</h3>
<blockquote>
<p>There is always a <a href="https://cr.yp.toc.tf/tasks/Rohald_86da9506b23e29e88d8c8f44965e9c2949a3dc41.txz">starting point</a>, isn’t it?</p>
</blockquote>
<p><code class="language-plaintext highlighter-rouge">RoHaLd_ECC.py</code></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env sage
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">flag</span><span class="p">,</span> <span class="n">Curve</span>
<span class="k">def</span> <span class="nf">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">):</span>
<span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="n">C</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">P</span>
<span class="k">return</span> <span class="p">(</span><span class="n">u</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">v</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">c</span><span class="o">**</span><span class="mi">2</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">u</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">v</span><span class="o">**</span><span class="mi">2</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">teal</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">Q</span><span class="p">):</span>
<span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="n">C</span>
<span class="n">u1</span><span class="p">,</span> <span class="n">v1</span> <span class="o">=</span> <span class="n">P</span>
<span class="n">u2</span><span class="p">,</span> <span class="n">v2</span> <span class="o">=</span> <span class="n">Q</span>
<span class="k">assert</span> <span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span> <span class="ow">and</span> <span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">Q</span><span class="p">)</span>
<span class="n">u3</span> <span class="o">=</span> <span class="p">(</span><span class="n">u1</span> <span class="o">*</span> <span class="n">v2</span> <span class="o">+</span> <span class="n">v1</span> <span class="o">*</span> <span class="n">u2</span><span class="p">)</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="n">c</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">u1</span> <span class="o">*</span> <span class="n">u2</span> <span class="o">*</span> <span class="n">v1</span> <span class="o">*</span> <span class="n">v2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">v3</span> <span class="o">=</span> <span class="p">(</span><span class="n">v1</span> <span class="o">*</span> <span class="n">v2</span> <span class="o">-</span> <span class="n">u1</span> <span class="o">*</span> <span class="n">u2</span><span class="p">)</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="n">c</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">d</span> <span class="o">*</span> <span class="n">u1</span> <span class="o">*</span> <span class="n">u2</span> <span class="o">*</span> <span class="n">v1</span> <span class="o">*</span> <span class="n">v2</span><span class="p">),</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">u3</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">v3</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">peam</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">m</span><span class="p">):</span>
<span class="k">assert</span> <span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span>
<span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="n">C</span>
<span class="n">B</span> <span class="o">=</span> <span class="nb">bin</span><span class="p">(</span><span class="n">m</span><span class="p">)[</span><span class="mi">2</span><span class="p">:]</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">B</span><span class="p">)</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">P</span>
<span class="n">PP</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
<span class="n">O</span> <span class="o">=</span> <span class="n">teal</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">PP</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">=</span> <span class="n">O</span>
<span class="k">if</span> <span class="n">m</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">O</span>
<span class="k">elif</span> <span class="n">m</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">P</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">l</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">teal</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">m</span> <span class="o">-</span> <span class="mi">2</span><span class="o">**</span><span class="p">(</span><span class="n">l</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">Q</span><span class="p">,</span> <span class="n">P</span> <span class="o">=</span> <span class="n">P</span><span class="p">,</span> <span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
<span class="k">return</span> <span class="n">teal</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">Q</span><span class="p">,</span> <span class="n">peam</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">m</span><span class="p">))</span>
<span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="n">Curve</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">flag</span><span class="p">.</span><span class="n">lstrip</span><span class="p">(</span><span class="sa">b</span><span class="s">'CCTF{'</span><span class="p">).</span><span class="n">rstrip</span><span class="p">(</span><span class="sa">b</span><span class="s">'}'</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">lflag</span><span class="p">,</span> <span class="n">rflag</span> <span class="o">=</span> <span class="n">flag</span><span class="p">[:</span><span class="n">l</span> <span class="o">//</span> <span class="mi">2</span><span class="p">],</span> <span class="n">flag</span><span class="p">[</span><span class="n">l</span> <span class="o">//</span> <span class="mi">2</span><span class="p">:]</span>
<span class="n">s</span><span class="p">,</span> <span class="n">t</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">lflag</span><span class="p">),</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">rflag</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">s</span> <span class="o"><</span> <span class="n">p</span> <span class="ow">and</span> <span class="n">t</span> <span class="o"><</span> <span class="n">p</span>
<span class="n">P</span> <span class="o">=</span> <span class="p">(</span><span class="mi">398011447251267732058427934569710020713094</span><span class="p">,</span> <span class="mi">548950454294712661054528329798266699762662</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">=</span> <span class="p">(</span><span class="mi">139255151342889674616838168412769112246165</span><span class="p">,</span> <span class="mi">649791718379009629228240558980851356197207</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'ison(C, P) = </span><span class="si">{</span><span class="n">ison</span><span class="p">(</span><span class="n">Curve</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'ison(C, Q) = </span><span class="si">{</span><span class="n">ison</span><span class="p">(</span><span class="n">Curve</span><span class="p">,</span> <span class="n">Q</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'P = </span><span class="si">{</span><span class="n">P</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Q = </span><span class="si">{</span><span class="n">Q</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'s * P = </span><span class="si">{</span><span class="n">peam</span><span class="p">(</span><span class="n">Curve</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'t * Q = </span><span class="si">{</span><span class="n">peam</span><span class="p">(</span><span class="n">Curve</span><span class="p">,</span> <span class="n">Q</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">output.txt</code></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span> <span class="o">=</span> <span class="bp">True</span>
<span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">Q</span><span class="p">)</span> <span class="o">=</span> <span class="bp">True</span>
<span class="n">P</span> <span class="o">=</span> <span class="p">(</span><span class="mi">398011447251267732058427934569710020713094</span><span class="p">,</span> <span class="mi">548950454294712661054528329798266699762662</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">=</span> <span class="p">(</span><span class="mi">139255151342889674616838168412769112246165</span><span class="p">,</span> <span class="mi">649791718379009629228240558980851356197207</span><span class="p">)</span>
<span class="n">s</span> <span class="o">*</span> <span class="n">P</span> <span class="o">=</span> <span class="p">(</span><span class="mi">730393937659426993430595540476247076383331</span><span class="p">,</span> <span class="mi">461597565155009635099537158476419433012710</span><span class="p">)</span>
<span class="n">t</span> <span class="o">*</span> <span class="n">Q</span> <span class="o">=</span> <span class="p">(</span><span class="mi">500532897653416664117493978883484252869079</span><span class="p">,</span> <span class="mi">620853965501593867437705135137758828401933</span><span class="p">)</span>
</code></pre></div></div>
<p>The challenge is to solve the discrete log problem twice, given two pairs of points on the curve. However, before we can do this, we need to recover the curve parameters $(c,d,p)$. The writeup is broken into two pieces: first the recovery of the paramters, then the mapping of the Edwards curve to Weierstrass form to easily solve the dlog using Sage.</p>
<h3 id="solution-4">Solution</h3>
<h4 id="recovering-curve-parameters">Recovering Curve Parameters</h4>
<p>Our goal in this section is to recover $(c,d,p)$ so we can reconstruct the curve and solve the discrete log. We will obtain $p$ first, which will allow us to take inversions mod $p$, needed to recover $c, d$.</p>
<p>We have the curve equation:</p>
\[E_{c,d} : x^2 + y^2 = c^2 (1 + d x^2 y^2) \pmod p\]
<p>and so we know for any point $(x_0,y_0)$ we have</p>
\[x_0^2 + y_0^2 - c^2 (1 + d x_0^2 y_0^2) = k_0 p \equiv 0\pmod p\]
<p>for some integer $k_0$.</p>
<p>Taking two points on the curve, we can isolate $cd^2$ using:</p>
\[X_1 = x_1^2 + y_1^2 - c^2 (1 + d x_1^2 y_1^2) = k_1 p \\
X_2 = x_2^2 + y_2^2 - c^2 (1 + d x_2^2 y_2^2) = k_2 p\]
<p>The goal is to use two points to write something which is a multiple of $p$, and to do this twice. We can then recover $p$ from the gcd of the pair of points.</p>
<p>Taking the difference $X_1 - X_2$ elliminates the constant $c^2$ term:</p>
\[X_1 - X_2 = (x_1^2 - x_2^2 + y_1^2 - y_2^2) - c^2d (x_1^2 y_1^2 - x_2^2 y_2^2) \equiv 0 \pmod p\]
<p>Collecting the multiples of $p$ we can isolate $c^2 d$ , where we use the notation:</p>
\[A_{ij} = x_i^2 - x_j^2 + y_i^2 - y_j^2, \qquad B_{ij} = x_i^2 y_i^2 - x_j^2 y_j^2\]
<p>to write down:</p>
\[\frac{A_{12}}{B_{12}} \equiv c^2 d \pmod p\]
<p>Doing this with the other pair of points gives another expression for $c^2 d$ and the difference of these two expressions will be a multiple of $p$</p>
\[\frac{A_{12}}{B_{12}} - \frac{A_{34}}{B_{34}} = k \cdot p\]
<p>There’s one more problem: we can’t divide without knowing $p$, so first let’s remove the denominator:</p>
\[A_{12} B_{34} - A_{34} B_{12} = B_{12}B_{34}kp = \tilde{k} p\]
<p>Finally, we can obtain $p$ from taking another combination of points and taking the $\gcd$</p>
\[\begin{aligned}
Y_{1234} &= A_{12} B_{34} - A_{34} B_{12} = B_{12}B_{34} \\
Y_{1324} &= A_{13} B_{24} - A_{24} B_{13} = B_{13}B_{24} \\
p &\simeq \gcd(Y_{1234}, Y_{1324})
\end{aligned}\]
<p>Note, we may not get exactly $p$ , but some multiple of $p$, however, it’s easy to factor this and find $p$ precisely.</p>
<p>Returning to the above expression with the knowledge of $p$, we can compute $c^2d$</p>
\[c^2 d = \frac{x_1^2 - x_2^2 + y_1^2 - y_2^2 }{x_1^2 y_1^2 - x_2^2 y_2^2} \pmod p\]
<p>and with this known, we can so back to any point on a curve and write</p>
\[c^2 = x_0^2 + y_0^2 - c^2 d x_0^2 y_0^2 \pmod p\]
<p>and $c$ is then found with a square root and $d$ can be found from $c^2 d$. With all curve parameters known, we can continue to solve the discrete log.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="k">def</span> <span class="nf">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">):</span>
<span class="s">"""
Verification points are on the curve
"""</span>
<span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span> <span class="o">=</span> <span class="n">C</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">P</span>
<span class="k">return</span> <span class="p">(</span><span class="n">u</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">v</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">cc</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">u</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">v</span><span class="o">**</span><span class="mi">2</span><span class="p">))</span> <span class="o">%</span> <span class="n">p</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">a_and_b</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">):</span>
<span class="s">"""
Helper function used to simplify calculations
"""</span>
<span class="n">a12</span> <span class="o">=</span> <span class="n">u1</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">u2</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">v1</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">v2</span><span class="o">**</span><span class="mi">2</span>
<span class="n">b12</span> <span class="o">=</span> <span class="n">u1</span><span class="o">**</span><span class="mi">2</span> <span class="o">*</span> <span class="n">v1</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">u2</span><span class="o">**</span><span class="mi">2</span> <span class="o">*</span> <span class="n">v2</span><span class="o">**</span><span class="mi">2</span>
<span class="k">return</span> <span class="n">a12</span><span class="p">,</span> <span class="n">b12</span>
<span class="k">def</span> <span class="nf">find_modulus</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">u3</span><span class="p">,</span><span class="n">u4</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">v3</span><span class="p">,</span><span class="n">v4</span><span class="p">):</span>
<span class="s">"""
Compute the modulus from four points
"""</span>
<span class="n">a12</span><span class="p">,</span> <span class="n">b12</span> <span class="o">=</span> <span class="n">a_and_b</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">)</span>
<span class="n">a13</span><span class="p">,</span> <span class="n">b13</span> <span class="o">=</span> <span class="n">a_and_b</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u3</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v3</span><span class="p">)</span>
<span class="n">a23</span><span class="p">,</span> <span class="n">b23</span> <span class="o">=</span> <span class="n">a_and_b</span><span class="p">(</span><span class="n">u2</span><span class="p">,</span><span class="n">u3</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">v3</span><span class="p">)</span>
<span class="n">a24</span><span class="p">,</span> <span class="n">b24</span> <span class="o">=</span> <span class="n">a_and_b</span><span class="p">(</span><span class="n">u2</span><span class="p">,</span><span class="n">u4</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">v4</span><span class="p">)</span>
<span class="n">p_almost</span> <span class="o">=</span> <span class="n">gcd</span><span class="p">(</span><span class="n">a12</span><span class="o">*</span><span class="n">b13</span> <span class="o">-</span> <span class="n">a13</span><span class="o">*</span><span class="n">b12</span><span class="p">,</span> <span class="n">a23</span><span class="o">*</span><span class="n">b24</span> <span class="o">-</span> <span class="n">a24</span><span class="o">*</span><span class="n">b23</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">1000</span><span class="p">):</span>
<span class="k">if</span> <span class="n">p_almost</span> <span class="o">%</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">p_almost</span> <span class="o">=</span> <span class="n">p_almost</span> <span class="o">//</span> <span class="n">i</span>
<span class="k">return</span> <span class="n">p_almost</span>
<span class="k">def</span> <span class="nf">c_sq_d</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">p</span><span class="p">):</span>
<span class="s">"""
Helper function to computer c^2 d
"""</span>
<span class="n">a1</span><span class="p">,</span><span class="n">b1</span> <span class="o">=</span> <span class="n">a_and_b</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">)</span>
<span class="k">return</span> <span class="n">a1</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">b1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">def</span> <span class="nf">c</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">p</span><span class="p">):</span>
<span class="s">"""
Compute c^2, d from two points and known modulus
"""</span>
<span class="n">ccd</span> <span class="o">=</span> <span class="n">c_sq_d</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">p</span><span class="p">)</span>
<span class="n">cc</span> <span class="o">=</span> <span class="p">(</span><span class="n">u1</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">v1</span><span class="o">**</span><span class="mi">2</span> <span class="o">-</span> <span class="n">ccd</span><span class="o">*</span><span class="n">u1</span><span class="o">**</span><span class="mi">2</span><span class="o">*</span><span class="n">v1</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">ccd</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">cc</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="o">%</span> <span class="n">p</span>
<span class="k">return</span> <span class="n">cc</span><span class="p">,</span> <span class="n">d</span>
<span class="n">P</span> <span class="o">=</span> <span class="p">(</span><span class="mi">398011447251267732058427934569710020713094</span><span class="p">,</span> <span class="mi">548950454294712661054528329798266699762662</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">=</span> <span class="p">(</span><span class="mi">139255151342889674616838168412769112246165</span><span class="p">,</span> <span class="mi">649791718379009629228240558980851356197207</span><span class="p">)</span>
<span class="n">sP</span> <span class="o">=</span> <span class="p">(</span><span class="mi">730393937659426993430595540476247076383331</span><span class="p">,</span> <span class="mi">461597565155009635099537158476419433012710</span><span class="p">)</span>
<span class="n">tQ</span> <span class="o">=</span> <span class="p">(</span><span class="mi">500532897653416664117493978883484252869079</span><span class="p">,</span> <span class="mi">620853965501593867437705135137758828401933</span><span class="p">)</span>
<span class="n">u1</span><span class="p">,</span> <span class="n">v1</span> <span class="o">=</span> <span class="n">P</span>
<span class="n">u2</span><span class="p">,</span> <span class="n">v2</span> <span class="o">=</span> <span class="n">Q</span>
<span class="n">u3</span><span class="p">,</span> <span class="n">v3</span> <span class="o">=</span> <span class="n">sP</span>
<span class="n">u4</span><span class="p">,</span> <span class="n">v4</span> <span class="o">=</span> <span class="n">tQ</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">find_modulus</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">u3</span><span class="p">,</span><span class="n">u4</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">v3</span><span class="p">,</span><span class="n">v4</span><span class="p">)</span>
<span class="n">cc</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">c</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span><span class="n">u2</span><span class="p">,</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">,</span><span class="n">p</span><span class="p">)</span>
<span class="n">C</span> <span class="o">=</span> <span class="n">cc</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span>
<span class="k">assert</span> <span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">P</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">Q</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">sP</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">ison</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">tQ</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Found curve parameters'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'p = </span><span class="si">{</span><span class="n">p</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'c^2 = </span><span class="si">{</span><span class="n">cc</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'d = </span><span class="si">{</span><span class="n">d</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="c1"># Found curve
# p = 903968861315877429495243431349919213155709
# cc = 495368774702871559312404847312353912297284
# d = 540431316779988345188678880301417602675534
</span></code></pre></div></div>
<h4 id="converting-to-weierstrass-form">Converting to Weierstrass Form</h4>
<p>With the curve known, all we have to do is solve the discrete log problem on the Edwards curve. This could be done by using Pohlih-Hellman and BSGS using the functions defined in the file, but instead we map the Edwards curve into Weierstrass form and use sage in built dlog to solve. Potentially there is a smarter way to do this conversion, here I used known mappings to go from Edwards to Montgomery form, then Montgomery form to Weierstrass form. Please let me know if there’s a smarter way to do this!</p>
<p>We begin with the Edwards curve:</p>
\[E_{c,d} : x^2 + y^2 = c^2 (1 + d x^2 y^2) \pmod p\]
<p>This is in the less usual form, with the factor $c$, so before continuing, we scale $(x,y,d)$ to remove $c$:</p>
\[x \to \frac{x}{c}, \; \; y \to \frac{y}{c}, \;\; d \to c^4 d\]
<p>To obtain the more familiar Edwards curve:</p>
\[E_{c} : x^2 + y^2 = (1 + d x^2 y^2) \pmod p\]
<p>Note: I am refering to $(x,y,d)$ using the same labels, I hope this doesnt confuse people.</p>
<p>In this more familiar form, I referred to https://safecurves.cr.yp.to/equation.html to map the curve to the Montgomery curve</p>
\[E_{A,B}: B v^2 = u^3 + Au^2 + u \pmod p\]
<p>With the factor $B$ here, I dont know how to create this curve using Sage, maybe this is possible? This mapping is done by the coordinate transformation</p>
\[u = \frac{1 + y}{1 - y}, \qquad v = \frac{2(1 + y)}{ x(1 - y)} = \frac{2u}{x}\]
<p>and the curve parameters are related by</p>
\[A = \frac{4}{1 - d } - 2 \qquad B = \frac{1}{1 - d }\]
<p>Finally, we can convert this curve to short Weierstrass form (equations are taken from https://en.wikipedia.org/wiki/Montgomery_curve)</p>
\[E_{a,b}: Y^2 = X^3 + aX^2 + b \pmod p\]
<p>My making the coordinate transformations</p>
\[X = \frac{u}{B} + \frac{A}{3B}, \qquad Y = \frac{v}{B}\]
<p>and the curve parameters are related by</p>
\[a = \frac{3 - A^2}{3B^2} \qquad b = \frac{2A^3 - 9A}{27B^3}\]
<p>In this form, we can plug the points into the curve using Sage and solve the discrete log. Implementation is given below</p>
<h4 id="grabbing-the-flag">Grabbing the flag</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="c1"># Recovered from previous section
</span><span class="n">p</span> <span class="o">=</span> <span class="mi">903968861315877429495243431349919213155709</span>
<span class="n">F</span> <span class="o">=</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">cc</span> <span class="o">=</span> <span class="mi">495368774702871559312404847312353912297284</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">cc</span><span class="p">).</span><span class="n">sqrt</span><span class="p">()</span>
<span class="n">d</span> <span class="o">=</span> <span class="mi">540431316779988345188678880301417602675534</span>
<span class="c1"># Point data from challenge
</span><span class="n">P</span> <span class="o">=</span> <span class="p">(</span><span class="mi">398011447251267732058427934569710020713094</span><span class="p">,</span> <span class="mi">548950454294712661054528329798266699762662</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">=</span> <span class="p">(</span><span class="mi">139255151342889674616838168412769112246165</span><span class="p">,</span> <span class="mi">649791718379009629228240558980851356197207</span><span class="p">)</span>
<span class="n">sP</span> <span class="o">=</span> <span class="p">(</span><span class="mi">730393937659426993430595540476247076383331</span><span class="p">,</span> <span class="mi">461597565155009635099537158476419433012710</span><span class="p">)</span>
<span class="n">tQ</span> <span class="o">=</span> <span class="p">(</span><span class="mi">500532897653416664117493978883484252869079</span><span class="p">,</span> <span class="mi">620853965501593867437705135137758828401933</span><span class="p">)</span>
<span class="n">x1</span><span class="p">,</span> <span class="n">y1</span> <span class="o">=</span> <span class="n">P</span>
<span class="n">x2</span><span class="p">,</span> <span class="n">y2</span> <span class="o">=</span> <span class="n">Q</span>
<span class="n">x3</span><span class="p">,</span> <span class="n">y3</span> <span class="o">=</span> <span class="n">sP</span>
<span class="n">x4</span><span class="p">,</span> <span class="n">y4</span> <span class="o">=</span> <span class="n">tQ</span>
<span class="n">R</span><span class="p">.</span><span class="o"><</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="o">></span> <span class="o">=</span> <span class="n">PolynomialRing</span><span class="p">(</span><span class="n">F</span><span class="p">)</span>
<span class="n">g</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="o">^</span><span class="mi">2</span> <span class="o">+</span> <span class="n">y</span><span class="o">^</span><span class="mi">2</span> <span class="o">-</span> <span class="n">cc</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">x</span><span class="o">^</span><span class="mi">2</span><span class="o">*</span><span class="n">y</span><span class="o">^</span><span class="mi">2</span><span class="p">))</span>
<span class="c1"># Check the mapping worked!
</span><span class="k">assert</span> <span class="n">g</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x1</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">g</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x2</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">g</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x3</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y3</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">g</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x4</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y4</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="c1"># Scale: x,y,d to remove c:
# x^2 + y^2 = c^2 * (1 + d * x^2*y^2)
# to:
# x^2 + y^2 = (1 + d * x^2*y^2)
</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="o">*</span> <span class="n">F</span><span class="p">(</span><span class="n">cc</span><span class="p">)</span><span class="o">^</span><span class="mi">2</span>
<span class="n">x1</span><span class="p">,</span> <span class="n">y1</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">x1</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">),</span> <span class="n">F</span><span class="p">(</span><span class="n">y1</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
<span class="n">x2</span><span class="p">,</span> <span class="n">y2</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">x2</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">),</span> <span class="n">F</span><span class="p">(</span><span class="n">y2</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
<span class="n">x3</span><span class="p">,</span> <span class="n">y3</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">x3</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">),</span> <span class="n">F</span><span class="p">(</span><span class="n">y3</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
<span class="n">x4</span><span class="p">,</span> <span class="n">y4</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">x4</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">),</span> <span class="n">F</span><span class="p">(</span><span class="n">y4</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
<span class="n">h</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="o">^</span><span class="mi">2</span> <span class="o">+</span> <span class="n">y</span><span class="o">^</span><span class="mi">2</span> <span class="o">-</span> <span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">d</span> <span class="o">*</span> <span class="n">x</span><span class="o">^</span><span class="mi">2</span><span class="o">*</span><span class="n">y</span><span class="o">^</span><span class="mi">2</span><span class="p">))</span>
<span class="c1"># Check the mapping worked!
</span><span class="k">assert</span> <span class="n">h</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x1</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">h</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x2</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">h</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x3</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y3</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">h</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x4</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">y4</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="c1"># Convert from Edwards to Mont.
# https://safecurves.cr.yp.to/equation.html
</span><span class="k">def</span> <span class="nf">ed_to_mont</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">):</span>
<span class="n">u</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span>
<span class="n">v</span> <span class="o">=</span> <span class="mi">2</span><span class="o">*</span><span class="n">F</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">y</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">y</span><span class="p">))</span>
<span class="k">return</span> <span class="n">u</span><span class="p">,</span><span class="n">v</span>
<span class="n">u1</span><span class="p">,</span> <span class="n">v1</span> <span class="o">=</span> <span class="n">ed_to_mont</span><span class="p">(</span><span class="n">x1</span><span class="p">,</span> <span class="n">y1</span><span class="p">)</span>
<span class="n">u2</span><span class="p">,</span> <span class="n">v2</span> <span class="o">=</span> <span class="n">ed_to_mont</span><span class="p">(</span><span class="n">x2</span><span class="p">,</span> <span class="n">y2</span><span class="p">)</span>
<span class="n">u3</span><span class="p">,</span> <span class="n">v3</span> <span class="o">=</span> <span class="n">ed_to_mont</span><span class="p">(</span><span class="n">x3</span><span class="p">,</span> <span class="n">y3</span><span class="p">)</span>
<span class="n">u4</span><span class="p">,</span> <span class="n">v4</span> <span class="o">=</span> <span class="n">ed_to_mont</span><span class="p">(</span><span class="n">x4</span><span class="p">,</span> <span class="n">y4</span><span class="p">)</span>
<span class="n">e_curve</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">F</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="n">A</span> <span class="o">=</span> <span class="p">(</span><span class="mi">4</span><span class="o">/</span><span class="n">e_curve</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">B</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="n">e_curve</span><span class="p">)</span>
<span class="c1"># Mont. curve: Bv^2 = u^3 + Au^2 + u
</span><span class="n">R</span><span class="p">.</span><span class="o"><</span><span class="n">u</span><span class="p">,</span><span class="n">v</span><span class="o">></span> <span class="o">=</span> <span class="n">PolynomialRing</span><span class="p">(</span><span class="n">ZZ</span><span class="p">)</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">B</span><span class="o">*</span><span class="n">v</span><span class="o">^</span><span class="mi">2</span> <span class="o">-</span> <span class="n">u</span><span class="o">^</span><span class="mi">3</span> <span class="o">-</span> <span class="n">A</span><span class="o">*</span> <span class="n">u</span><span class="o">^</span><span class="mi">2</span> <span class="o">-</span> <span class="n">u</span>
<span class="c1"># Check the mapping worked!
</span><span class="k">assert</span> <span class="n">f</span><span class="p">(</span><span class="n">u</span><span class="o">=</span><span class="n">u1</span><span class="p">,</span> <span class="n">v</span><span class="o">=</span><span class="n">v1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">f</span><span class="p">(</span><span class="n">u</span><span class="o">=</span><span class="n">u2</span><span class="p">,</span> <span class="n">v</span><span class="o">=</span><span class="n">v2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">f</span><span class="p">(</span><span class="n">u</span><span class="o">=</span><span class="n">u3</span><span class="p">,</span> <span class="n">v</span><span class="o">=</span><span class="n">v3</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">f</span><span class="p">(</span><span class="n">u</span><span class="o">=</span><span class="n">u4</span><span class="p">,</span> <span class="n">v</span><span class="o">=</span><span class="n">v4</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="c1"># Convert from Mont. to Weierstrass
# https://en.wikipedia.org/wiki/Montgomery_curve
</span><span class="n">a</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="mi">3</span> <span class="o">-</span> <span class="n">A</span><span class="o">^</span><span class="mi">2</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="mi">3</span><span class="o">*</span><span class="n">B</span><span class="o">^</span><span class="mi">2</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">A</span><span class="o">^</span><span class="mi">3</span> <span class="o">-</span> <span class="mi">9</span><span class="o">*</span><span class="n">A</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="mi">27</span><span class="o">*</span><span class="n">B</span><span class="o">^</span><span class="mi">3</span><span class="p">)</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">EllipticCurve</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">])</span>
<span class="c1"># https://en.wikipedia.org/wiki/Montgomery_curve
</span><span class="k">def</span> <span class="nf">mont_to_wei</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">v</span><span class="p">):</span>
<span class="n">t</span> <span class="o">=</span> <span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="n">u</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">B</span><span class="p">))</span> <span class="o">+</span> <span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="n">A</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="mi">3</span><span class="o">*</span><span class="n">B</span><span class="p">))</span>
<span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="n">F</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">/</span> <span class="n">F</span><span class="p">(</span><span class="n">B</span><span class="p">))</span>
<span class="k">return</span> <span class="n">t</span><span class="p">,</span><span class="n">s</span>
<span class="n">X1</span><span class="p">,</span> <span class="n">Y1</span> <span class="o">=</span> <span class="n">mont_to_wei</span><span class="p">(</span><span class="n">u1</span><span class="p">,</span> <span class="n">v1</span><span class="p">)</span>
<span class="n">X2</span><span class="p">,</span> <span class="n">Y2</span> <span class="o">=</span> <span class="n">mont_to_wei</span><span class="p">(</span><span class="n">u2</span><span class="p">,</span> <span class="n">v2</span><span class="p">)</span>
<span class="n">X3</span><span class="p">,</span> <span class="n">Y3</span> <span class="o">=</span> <span class="n">mont_to_wei</span><span class="p">(</span><span class="n">u3</span><span class="p">,</span> <span class="n">v3</span><span class="p">)</span>
<span class="n">X4</span><span class="p">,</span> <span class="n">Y4</span> <span class="o">=</span> <span class="n">mont_to_wei</span><span class="p">(</span><span class="n">u4</span><span class="p">,</span> <span class="n">v4</span><span class="p">)</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="n">X1</span><span class="p">,</span> <span class="n">Y1</span><span class="p">)</span>
<span class="n">Q</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="n">X2</span><span class="p">,</span> <span class="n">Y2</span><span class="p">)</span>
<span class="n">sP</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="n">X3</span><span class="p">,</span> <span class="n">Y3</span><span class="p">)</span>
<span class="n">tQ</span> <span class="o">=</span> <span class="n">E</span><span class="p">(</span><span class="n">X4</span><span class="p">,</span> <span class="n">Y4</span><span class="p">)</span>
<span class="c1"># Finally we can solve the dlog
</span><span class="n">s</span> <span class="o">=</span> <span class="n">P</span><span class="p">.</span><span class="n">discrete_log</span><span class="p">(</span><span class="n">sP</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">Q</span><span class="p">.</span><span class="n">discrete_log</span><span class="p">(</span><span class="n">tQ</span><span class="p">)</span>
<span class="c1"># This should be the flag, but s is broken
</span><span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">s</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">t</span><span class="p">))</span>
<span class="c1"># b'\x05\x9e\x92\xbfO\xdf1\x16\xb0>s\x93\xc6\xc7\xe7\xa3\x80\xf0'
# b'Ds_3LlipT!c_CURv3'
</span>
<span class="c1"># We have to do this, as we picked the wrong square-root.
</span><span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">s</span> <span class="o">%</span> <span class="n">Q</span><span class="p">.</span><span class="n">order</span><span class="p">()))</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">t</span><span class="p">))</span>
<span class="c1"># b'nOt_50_3a5Y_Edw4r'
# b'Ds_3LlipT!c_CURv3'
</span></code></pre></div></div>
<h5 id="flag-4">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{nOt_50_3a5Y_Edw4rDs_3LlipT!c_CURv3}</code></p>
<h4 id="wrong-root">Wrong Root</h4>
<p>When recovering the parameters we find:</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Recovered from previous section
</span><span class="n">p</span> <span class="o">=</span> <span class="mi">903968861315877429495243431349919213155709</span>
<span class="n">F</span> <span class="o">=</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">cc</span> <span class="o">=</span> <span class="mi">495368774702871559312404847312353912297284</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="n">cc</span><span class="p">).</span><span class="n">sqrt</span><span class="p">()</span>
<span class="n">d</span> <span class="o">=</span> <span class="mi">540431316779988345188678880301417602675534</span>
</code></pre></div></div>
<p>however, there are two square roots to consider. By picking the wrong one, we introduce a minus sign in the scaling of the curves from $E_{a,c}$ to $E_{a}$ which creates an issue with the point we consider in $E_{A,B}$. This can be fixed by instead working with</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Recovered from previous section
</span><span class="n">p</span> <span class="o">=</span> <span class="mi">903968861315877429495243431349919213155709</span>
<span class="n">F</span> <span class="o">=</span> <span class="n">GF</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">cc</span> <span class="o">=</span> <span class="mi">495368774702871559312404847312353912297284</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">F</span><span class="p">((</span><span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">F</span><span class="p">(</span><span class="n">cc</span><span class="p">).</span><span class="n">sqrt</span><span class="p">()))</span>
<span class="n">d</span> <span class="o">=</span> <span class="mi">540431316779988345188678880301417602675534</span>
</code></pre></div></div>
<p>which would mean we did not need to take the reduction mod <code class="language-plaintext highlighter-rouge">Q.order()</code></p>
<h2 id="robert">Robert</h2>
<h3 id="challenge-5">Challenge</h3>
<blockquote>
<p>Oh, Robert, you can always handle everything!
<code class="language-plaintext highlighter-rouge">nc 07.cr.yp.toc.tf 10101</code></p>
</blockquote>
<p>Upon connection, we see</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ hi all, all cryptographers know that fast calculation is not easy! +
+ In each stage for given integer m, find number n such that: +
+ carmichael_lambda(n) = m, e.g. carmichael_lambda(2021) = 966 +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| send an integer n such that carmichael_lambda(n) = 52:
</code></pre></div></div>
<p>where we can of course assume we will need to pass a certain number of rounds, and the numbers will grow.</p>
<h3 id="solution-5">Solution</h3>
<p>Early on, we find <a href="https://math.stackexchange.com/questions/41061/what-is-the-inverse-of-the-carmichael-function">this math stackexchange post</a>, where we already make the comment</p>
<blockquote>
<p>looks hard</p>
</blockquote>
<p>as, in general, this problem appears to be at least as hard as factoring $m$.
We consider the possibility of factoring $m$ and applying a dynamic programming based approach to group the prime factors of $m$ among the prime factors of what would be $n$.
In the end, this did not get implemented, as our intermediate attempts at cheesy solutions converge towards a simpler approach that solves the challenge.
The first of these cheesy attempts comes from 3m4 – while setting the basis for further server communication scripts – where we simply cross our fingers and hope that $m + 1$ is prime, leading to $n = m + 1$ and $\lambda(n) = m$.
While this clears up to 6 rounds on numerous occasions, it appears we’d need to either hammer the server really hard, or find something better.
Somewhere during this period of running our cheesy script full of hope, dd suggests that we might be in a situations where $m$ is known to be derived from a semiprime originally, i.e. $m = \lambda(pq)$.
Alongside this idea, an attempted solution exploiting that property is proposed, that unfortunately has several flaws and doesn’t work against the server.</p>
<p>Basing ourselves on this idea, we can however write the dumbest sage script imaginable for this problem:</p>
<ul>
<li>Let $D$ be the set of divisors of $m$</li>
<li>Enumerate all $(a, b) \in D^2$</li>
<li>If $a + 1$ is prime, $b + 1$ is prime, <em>and</em> $\mathsf{lcm}(a, b) = m$: reply with $n = (a + 1)(b + 1)$</li>
</ul>
<p>Clearly, <em>if</em> our assumed property that $m = \lambda(pq)$ holds, and $m$ does not grow too large to enumerate $D^2$, this should give us a correct solution.</p>
<p>Without all too much hope, we run the following sage script (with the <code class="language-plaintext highlighter-rouge">DEBUG</code> command line argument for pwntools, so that we can observe the flag should it get sent at the end):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">os</span>
<span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">"PWNLIB_NOTERM"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"true"</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">remote</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"07.cr.yp.toc.tf"</span><span class="p">,</span> <span class="mi">10101</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"</span><span class="p">)</span>
<span class="n">proof</span><span class="p">.</span><span class="n">arithmetic</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">reverse_lambda</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">divisors</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">divisors</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">lcm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">==</span> <span class="n">n</span> <span class="ow">and</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="ow">and</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"carmichael_lambda(n) = "</span><span class="p">)</span>
<span class="n">integer</span> <span class="o">=</span> <span class="n">ZZ</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">":"</span><span class="p">)[:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[*] Reversed: </span><span class="si">{</span><span class="n">integer</span><span class="si">}</span><span class="s"> ->"</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">" "</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">rev</span> <span class="o">=</span> <span class="n">reverse_lambda</span><span class="p">(</span><span class="n">integer</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">rev</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">rev</span><span class="p">).</span><span class="n">encode</span><span class="p">())</span>
<span class="k">except</span> <span class="nb">EOFError</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"EOF"</span><span class="p">)</span>
</code></pre></div></div>
<p>Against our initial expectations, we easily clear more than 10 rounds.
Slowing down on an occasional $m$ that might have been hard to factor or have a lot of different divisors, the script happily chugs along without the server closing the connection on it, eventually getting the flag after 20 rounds.</p>
<h5 id="flag-5">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{Carmichael_numbers_are_Fermat_pseudo_primes}</code></p>
<h2 id="trunc">Trunc</h2>
<h3 id="challenge-6">Challenge</h3>
<blockquote>
<p>I wish I could say more, but I don’t want to!
<code class="language-plaintext highlighter-rouge">nc 02.cr.yp.toc.tf 23010</code>
<a href="https://cr.yp.toc.tf/tasks/TRUNC_dd1e2d91b790125fdfc7596f0076fa476446d2fb.txz">TRUNC.txz</a></p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="n">sha256</span>
<span class="kn">import</span> <span class="nn">ecdsa</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">FLAG</span>
<span class="n">E</span> <span class="o">=</span> <span class="n">ecdsa</span><span class="p">.</span><span class="n">SECP256k1</span>
<span class="n">G</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="n">E</span><span class="p">.</span><span class="n">generator</span><span class="p">,</span> <span class="n">E</span><span class="p">.</span><span class="n">order</span>
<span class="n">cryptonym</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'Persian Gulf'</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">G</span><span class="p">):</span>
<span class="n">privkey</span> <span class="o">=</span> <span class="n">getRandomRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">pubkey</span> <span class="o">=</span> <span class="n">privkey</span> <span class="o">*</span> <span class="n">G</span>
<span class="k">return</span> <span class="p">(</span><span class="n">pubkey</span><span class="p">,</span> <span class="n">privkey</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">sign</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">keypair</span><span class="p">):</span>
<span class="n">nbit</span><span class="p">,</span> <span class="n">dbit</span> <span class="o">=</span> <span class="mi">256</span><span class="p">,</span> <span class="mi">25</span>
<span class="n">pubkey</span><span class="p">,</span> <span class="n">privkey</span> <span class="o">=</span> <span class="n">keypair</span>
<span class="n">privkey_bytes</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="n">privkey</span><span class="p">)</span>
<span class="n">x</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sha256</span><span class="p">(</span><span class="n">privkey_bytes</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span><span class="o">**</span><span class="n">dbit</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">k</span><span class="p">,</span> <span class="n">l</span> <span class="o">=</span> <span class="p">[(</span><span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="n">nbit</span><span class="p">)</span> <span class="o"><<</span> <span class="n">dbit</span><span class="p">)</span> <span class="o">+</span> <span class="n">x</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="s">'01'</span><span class="p">]</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="p">(</span><span class="n">k</span> <span class="o">*</span> <span class="n">G</span><span class="p">).</span><span class="n">x</span><span class="p">(),</span> <span class="p">(</span><span class="n">l</span> <span class="o">*</span> <span class="n">G</span><span class="p">).</span><span class="n">y</span><span class="p">()</span>
<span class="k">if</span> <span class="n">u</span> <span class="o">+</span> <span class="n">v</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">h</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sha256</span><span class="p">(</span><span class="n">msg</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">inverse</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">h</span> <span class="o">*</span> <span class="n">u</span> <span class="o">-</span> <span class="n">v</span> <span class="o">*</span> <span class="n">privkey</span><span class="p">)</span> <span class="o">%</span> <span class="n">n</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">u</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">v</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">verify</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">,</span> <span class="n">sig</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="n">x</span> <span class="o"><</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">x</span> <span class="o">>=</span> <span class="n">n</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sig</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">s</span> <span class="o">=</span> <span class="n">sig</span>
<span class="n">h</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sha256</span><span class="p">(</span><span class="n">msg</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">k</span><span class="p">,</span> <span class="n">l</span> <span class="o">=</span> <span class="n">h</span> <span class="o">*</span> <span class="n">u</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">),</span> <span class="n">v</span> <span class="o">*</span> <span class="n">inverse</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">X</span> <span class="o">=</span> <span class="p">(</span><span class="n">k</span> <span class="o">*</span> <span class="n">G</span> <span class="o">+</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="n">l</span><span class="p">)</span> <span class="o">*</span> <span class="n">pubkey</span><span class="p">).</span><span class="n">x</span><span class="p">()</span>
<span class="k">return</span> <span class="p">(</span><span class="n">X</span> <span class="o">-</span> <span class="n">u</span><span class="p">)</span> <span class="o">%</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">die</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">quit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">pr</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">sc</span><span class="p">():</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdin</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">border</span> <span class="o">=</span> <span class="s">"+"</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" hi all, welcome to the high secure elliptic curve signature oracle!"</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="p">,</span> <span class="s">" Your mission is to sign the out cryptonym, try your best :) "</span><span class="p">,</span> <span class="n">border</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="n">border</span><span class="o">*</span><span class="mi">72</span><span class="p">)</span>
<span class="n">keypair</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">G</span><span class="p">)</span>
<span class="n">pubkey</span><span class="p">,</span> <span class="n">privkey</span> <span class="o">=</span> <span class="n">keypair</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| Options: </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[P]rint the pubkey </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[S]ign </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[V]erify </span><span class="se">\n</span><span class="s">|</span><span class="se">\t</span><span class="s">[Q]uit"</span><span class="p">)</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">sc</span><span class="p">().</span><span class="n">lower</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'p'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| pubkey ="</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">.</span><span class="n">x</span><span class="p">(),</span> <span class="n">pubkey</span><span class="p">.</span><span class="n">y</span><span class="p">())</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'s'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| send your hex message to sign: "</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">msg</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your message is not valid! Bye!!"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">msg</span> <span class="o">==</span> <span class="n">cryptonym</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">'| Kidding me? Bye'</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">msg</span><span class="p">[:</span><span class="mi">14</span><span class="p">]</span>
<span class="n">sig</span> <span class="o">=</span> <span class="n">sign</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">keypair</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| sign ="</span><span class="p">,</span> <span class="n">sig</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'v'</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| send your hex message to verify: "</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">msg</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your message is not valid! Bye!!"</span><span class="p">)</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| send the signature separated with comma: "</span><span class="p">)</span>
<span class="n">sig</span> <span class="o">=</span> <span class="n">sc</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">sig</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">sig</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)]</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your signature is not valid! Bye!!"</span><span class="p">)</span>
<span class="k">if</span> <span class="n">verify</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">,</span> <span class="n">sig</span><span class="p">):</span>
<span class="k">if</span> <span class="n">msg</span> <span class="o">==</span> <span class="n">cryptonym</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| Good job! Congrats, the flag is:"</span><span class="p">,</span> <span class="n">FLAG</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">pr</span><span class="p">(</span><span class="s">"| your message is verified!!"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"| your signature is not valid! Bye!!"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">ans</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Quitting ..."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">die</span><span class="p">(</span><span class="s">"Bye ..."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<h3 id="solution-6">Solution</h3>
<p>Here we have a ECDSA-like signature scheme: nonces $k$ and $l$ are generated in such a way, that they always have their 25 LSBs dependent only on private key, thus always the same, then $u$ and $v$ are obtained as $x$-coordinates of $kG$ and $lG$ respectively, where $G$ is a generator on the curve <code class="language-plaintext highlighter-rouge">secp256k1</code>, then $h$ = <code class="language-plaintext highlighter-rouge">sha256(msg)</code> and $s \equiv k^{-1}(hu - vd) \mod n$ are computed, where $d$ is the private key and $n$ is the order of the curve. $(u, v, s)$ is a signature for $h$.</p>
<p>Verification works as follows: again, $h$ = <code class="language-plaintext highlighter-rouge">sha256(msg)</code> is computed, then $k \equiv hus^{-1} \mod n$ and $l \equiv vs^{-1} \mod n$ are computed, after that $X$ is derived as $x$-coordinate of $kG - lP$, where $P = G * d$ is the public key. Signature verifies iff $X \equiv u \mod n$.
During interaction with the service we can obtain the public key by sending <code class="language-plaintext highlighter-rouge">p</code>, sign any message (except <code class="language-plaintext highlighter-rouge">Persian Gulf</code>) by sending <code class="language-plaintext highlighter-rouge">s</code>, verify a signature for a message with <code class="language-plaintext highlighter-rouge">v</code>, and if the signature for <code class="language-plaintext highlighter-rouge">Persian Gulf</code> verifies, we are given the flag, and quit with <code class="language-plaintext highlighter-rouge">q</code>.</p>
<p>This is an unintended solution, which doesn’t exploit odd nonce generation during signature creation.
If $h_1$ is a hash of some message $m$, and $h_2$ is the hash for <code class="language-plaintext highlighter-rouge">Persian Gulf</code>, we can write $h_2 \equiv m h_1 \mod n$, and if $(u_1, v_1, s_1)$ is a valid signature for $h_1$, then $(u_1, v_1m, s_1m)$ is a valid signature for $h_2$.</p>
<p>Proof: during verification of $h_1$ we have $k \equiv h_1u_1s_1^{-1} \mod n$ and $l \equiv v_1s_1^{-1} \mod n$. During verification of $h_2$ we have $k \equiv h_1mu_1(ms_1)^{-1} \equiv h_1mu_1m^{-1}s_1^{-1} \equiv h_1u_1s_1^{-1}\mod n$ and $l \equiv v_1m(s_1m)^{-1} \equiv v_1ms_1^{-1}m^{-1} \equiv v_1s_1^{-1}\mod n$, so $k, l$ are the same, thus $X$ is the same. And since $u$ is also the same, this signature will also verify.</p>
<h4 id="implementation-1">Implementation</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="n">remote</span>
<span class="kn">from</span> <span class="nn">ecdsa</span> <span class="kn">import</span> <span class="n">SECP256k1</span>
<span class="kn">from</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="n">sha256</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">SECP256k1</span><span class="p">.</span><span class="n">order</span>
<span class="n">m1</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'lol'</span> <span class="c1"># any other message is fine
</span><span class="n">m2</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'Persian Gulf'</span>
<span class="n">h1</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sha256</span><span class="p">(</span><span class="n">m1</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">h2</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sha256</span><span class="p">(</span><span class="n">m2</span><span class="p">).</span><span class="n">hexdigest</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">h2</span> <span class="o">*</span> <span class="nb">pow</span><span class="p">(</span><span class="n">h1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="n">n</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"02.cr.yp.toc.tf"</span><span class="p">,</span> <span class="mi">23010</span><span class="p">)</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">9</span><span class="p">):</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'s'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">m1</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>
<span class="n">u1</span><span class="p">,</span> <span class="n">v1</span><span class="p">,</span> <span class="n">w1</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">()[</span><span class="mi">8</span><span class="p">:])</span>
<span class="n">u2</span><span class="p">,</span> <span class="n">v2</span><span class="p">,</span> <span class="n">w2</span> <span class="o">=</span> <span class="n">u1</span><span class="p">,</span> <span class="n">v1</span> <span class="o">*</span> <span class="n">m</span> <span class="o">%</span> <span class="n">n</span><span class="p">,</span> <span class="n">w1</span> <span class="o">*</span> <span class="n">m</span> <span class="o">%</span> <span class="n">n</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'v'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">m2</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">','</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="p">[</span><span class="n">u2</span><span class="p">,</span> <span class="n">v2</span><span class="p">,</span> <span class="n">w2</span><span class="p">])))</span>
<span class="k">print</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">decode</span><span class="p">().</span><span class="n">strip</span><span class="p">().</span><span class="n">split</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="n">r</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<h5 id="flag-6">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{__ECC_Bi4seD_N0nCE_53ns3_LLL!!!}</code></p>
<h2 id="my-sieve">My Sieve</h2>
<h3 id="challenge-7">Challenge</h3>
<blockquote>
<p>We have captured one of the most brilliant spies who successfully broke a private key! All the <a href="https://cr.yp.toc.tf/tasks/recovered_54f706f7fb8fc9718a4600d0000987ea4bcb03d8.txz">information</a> gathered and we believe they are enough to reconstruct the way he used to break the key. Now, can you help us to find the secret message?</p>
</blockquote>
<p>We are given the encrypted flag:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>enc = 17774316754182701043637765672766475504513144507864625935518462040899856505354546178499264702656639970102754546327338873353871389580967004810214134215521924626871944954513679198245322915573598165643628084858678915415521536126034275104881281802618561405075363713125886815998055449593678564456363170087233864817
</code></pre></div></div>
<p>A corrupted pem file:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB*QKBgQCkRgRCyTcSwlBKmERQV/BHkurS
5QnYz7Rm18OjxuuWT3A*Ueqzq7fHISey2NEEtral/*E7v2Dy59DYHoRAAouWQd03
ZYWnvU5mWoYRcpNmHIj8q*+FOtBWcCGzMZ8uxOxaV74vqqerjxyRI14rXZ+QOcNM
/TMM84h0rl/IKqqWsQIDAQAB
-----END PUBLIC KEY-----
</code></pre></div></div>
<p>and a <code class="language-plaintext highlighter-rouge">msieve.dat</code> file, which is a file outputted while using msieve https://github.com/radii/msieve.</p>
<h3 id="solution-7">Solution</h3>
<h4 id="msieve">Msieve</h4>
<p>Looking at the data file, we see that a <code class="language-plaintext highlighter-rouge">~350</code> bit number</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x1dabd3bb8e99101030cd7094eb15dd525cb0f02065694604071c2a8b10228f30cc12d08fc9caa8d97c65ff481
</code></pre></div></div>
<p>was factored. We can recover the factors using the command:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./msieve 17012713766362055606937340593828012836774345940104644978558327325254454345526470012917476548051189037528193
</code></pre></div></div>
<p>where we must ensure the data file is in the correct directory. Looking into the log file we find:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Fri Jul 30 19:34:05 2021 Msieve v. 1.46
Fri Jul 30 19:34:05 2021 random seeds: 98cfb443 69ab82cc
Fri Jul 30 19:34:05 2021 factoring 17012713766362055606937340593828012836774345940104644978558327325254454345526470012917476548051189037528193 (107 digits)
Fri Jul 30 19:34:06 2021 no P-1/P+1/ECM available, skipping
Fri Jul 30 19:34:06 2021 commencing quadratic sieve (106-digit input)
Fri Jul 30 19:34:06 2021 using multiplier of 11
Fri Jul 30 19:34:06 2021 using generic 32kb sieve core
Fri Jul 30 19:34:06 2021 sieve interval: 39 blocks of size 32768
Fri Jul 30 19:34:06 2021 processing polynomials in batches of 6
Fri Jul 30 19:34:06 2021 using a sieve bound of 4223251 (149333 primes)
Fri Jul 30 19:34:06 2021 using large prime bound of 633487650 (29 bits)
Fri Jul 30 19:34:06 2021 using double large prime bound of 6968329308179250 (45-53 bits)
Fri Jul 30 19:34:06 2021 using trial factoring cutoff of 53 bits
Fri Jul 30 19:34:06 2021 polynomial 'A' values have 14 factors
Fri Jul 30 19:34:06 2021 restarting with 35905 full and 2217078 partial relations
Fri Jul 30 19:34:06 2021 149536 relations (35905 full + 113631 combined from 2217078 partial), need 149429
Fri Jul 30 19:34:07 2021 begin with 2252983 relations
Fri Jul 30 19:34:07 2021 reduce to 393304 relations in 11 passes
Fri Jul 30 19:34:07 2021 attempting to read 393304 relations
Fri Jul 30 19:34:08 2021 recovered 393304 relations
Fri Jul 30 19:34:08 2021 recovered 385553 polynomials
Fri Jul 30 19:34:08 2021 attempting to build 149536 cycles
Fri Jul 30 19:34:08 2021 found 149535 cycles in 5 passes
Fri Jul 30 19:34:08 2021 distribution of cycle lengths:
Fri Jul 30 19:34:08 2021 length 1 : 35905
Fri Jul 30 19:34:08 2021 length 2 : 25563
Fri Jul 30 19:34:08 2021 length 3 : 24612
Fri Jul 30 19:34:08 2021 length 4 : 20585
Fri Jul 30 19:34:08 2021 length 5 : 15651
Fri Jul 30 19:34:08 2021 length 6 : 10638
Fri Jul 30 19:34:08 2021 length 7 : 6982
Fri Jul 30 19:34:08 2021 length 9+: 9599
Fri Jul 30 19:34:08 2021 largest cycle: 19 relations
Fri Jul 30 19:34:08 2021 matrix is 149333 x 149535 (43.3 MB) with weight 10166647 (67.99/col)
Fri Jul 30 19:34:08 2021 sparse part has weight 10166647 (67.99/col)
Fri Jul 30 19:34:09 2021 filtering completed in 3 passes
Fri Jul 30 19:34:09 2021 matrix is 143467 x 143531 (41.8 MB) with weight 9815366 (68.38/col)
Fri Jul 30 19:34:09 2021 sparse part has weight 9815366 (68.38/col)
Fri Jul 30 19:34:09 2021 saving the first 48 matrix rows for later
Fri Jul 30 19:34:09 2021 matrix is 143419 x 143531 (24.4 MB) with weight 7565741 (52.71/col)
Fri Jul 30 19:34:09 2021 sparse part has weight 4961307 (34.57/col)
Fri Jul 30 19:34:09 2021 matrix includes 64 packed rows
Fri Jul 30 19:34:09 2021 using block size 57412 for processor cache size 65536 kB
Fri Jul 30 19:34:09 2021 commencing Lanczos iteration
Fri Jul 30 19:34:09 2021 memory use: 24.2 MB
Fri Jul 30 19:34:10 2021 linear algebra at 4.2%, ETA 0h 0m
Fri Jul 30 19:34:34 2021 lanczos halted after 2270 iterations (dim = 143416)
Fri Jul 30 19:34:34 2021 recovered 16 nontrivial dependencies
Fri Jul 30 19:34:35 2021 p2 factor: 11
Fri Jul 30 19:34:35 2021 prp53 factor: 37517726695590864161261967849116722975727713562769161
Fri Jul 30 19:34:35 2021 prp53 factor: 41223455646589331474862018682296591762663841134030283
Fri Jul 30 19:34:35 2021 elapsed time 00:00:30
</code></pre></div></div>
<p>and so we have the three factors of the number:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Fri Jul 30 19:34:35 2021 p2 factor: 11
Fri Jul 30 19:34:35 2021 prp53 factor: 37517726695590864161261967849116722975727713562769161
Fri Jul 30 19:34:35 2021 prp53 factor: 41223455646589331474862018682296591762663841134030283
</code></pre></div></div>
<p>Now the question was, how does this 350 bit integer relate to the corrupted public key?</p>
<h4 id="corrupted-key">Corrupted Key</h4>
<p>Looking at the corrupted key, we see 4 <code class="language-plaintext highlighter-rouge">*</code> though the file. This means naively we have <code class="language-plaintext highlighter-rouge">64**4</code> different <code class="language-plaintext highlighter-rouge">N</code> which are valid. The assumption was that one of these <code class="language-plaintext highlighter-rouge">N</code> would share factors the factored number from msieve.</p>
<p>Looking into the pem format, we actually find the first character must be <code class="language-plaintext highlighter-rouge">i</code> and so only three chr remain to be searched through. To try and find the correct <code class="language-plaintext highlighter-rouge">N</code> we looked for <code class="language-plaintext highlighter-rouge">gcd(X,N)!=0</code> for all possible keys:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="n">corrupt_N</span> <span class="o">=</span> <span class="mh">0xa4460442c93712c2504a98445057f04792ead2e509d8cfb466d7c3a3c6eb964f700051eab3abb7c72127b2d8d104b6b6a5fc013bbf60f2e7d0d81e8440028b9641dd376585a7bd4e665a86117293661c88fca80f853ad0567021b3319f2ec4ec5a57be2faaa7ab8f1c91235e2b5d9f9039c34cfd330cf38874ae5fc82aaa96b1</span>
<span class="n">X</span> <span class="o">=</span> <span class="mh">0x1dabd3bb8e99101030cd7094eb15dd525cb0f02065694604071c2a8b10228f30cc12d08fc9caa8d97c65ff481</span>
<span class="n">offsets</span> <span class="o">=</span> <span class="p">[</span><span class="mi">356</span><span class="p">,</span> <span class="mi">620</span><span class="p">,</span> <span class="mi">752</span><span class="p">]</span>
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">64</span><span class="p">):</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">64</span><span class="p">):</span>
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">64</span><span class="p">):</span>
<span class="n">N</span> <span class="o">=</span> <span class="n">corrupt_N</span> <span class="o">|</span> <span class="p">(</span><span class="n">a</span><span class="o"><<</span><span class="n">offsets</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">|</span> <span class="p">(</span><span class="n">b</span><span class="o"><<</span><span class="n">offsets</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">|</span> <span class="p">(</span><span class="n">c</span><span class="o"><<</span><span class="n">offsets</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
<span class="k">if</span> <span class="n">gcd</span><span class="p">(</span><span class="n">N</span><span class="p">,</span> <span class="n">X</span><span class="p">)</span> <span class="o">></span> <span class="mi">2</span><span class="o">**</span><span class="mi">32</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"w00t"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">N</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">gcd</span><span class="p">(</span><span class="n">N</span><span class="p">,</span> <span class="n">X</span><span class="p">))</span>
</code></pre></div></div>
<p>However, running this script we found no values of <code class="language-plaintext highlighter-rouge">N</code> which had <code class="language-plaintext highlighter-rouge">X</code>, or a factor of <code class="language-plaintext highlighter-rouge">X</code> as a common divisor. The rest of the CTF we tried guessing other things, but nothing worked out.</p>
<p>During the CTF, this was solved once, by HXP, who solved it by using <code class="language-plaintext highlighter-rouge">X//11</code> as the public key:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">p</span> <span class="o">=</span> <span class="mi">37517726695590864161261967849116722975727713562769161</span>
<span class="n">q</span> <span class="o">=</span> <span class="mi">41223455646589331474862018682296591762663841134030283</span>
<span class="n">N</span> <span class="o">=</span> <span class="n">p</span><span class="o">*</span><span class="n">q</span>
<span class="n">phi</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">e</span> <span class="o">=</span> <span class="mh">0x10001</span>
<span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">phi</span><span class="p">)</span>
<span class="n">enc</span> <span class="o">=</span> <span class="mi">17774316754182701043637765672766475504513144507864625935518462040899856505354546178499264702656639970102754546327338873353871389580967004810214134215521924626871944954513679198245322915573598165643628084858678915415521536126034275104881281802618561405075363713125886815998055449593678564456363170087233864817</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">enc</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">N</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="c1"># b'CCTF{l34Rn_WorK_bY__Msieve__A5aP}'
</span></code></pre></div></div>
<p>This was an unintended solution, and worked as the flag was small enough. Seeing this, it’s dissapointing that we didnt try this guess, but we were so sure the .pem was needed for the solve, I guess this didnt occur to any of us.</p>
<h3 id="true-solution">True Solution</h3>
<p>After the CTF ended, the real pem was released.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat pubkey.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkRgRCyTcSwlBKmERQV/BHkurT
5QnYz7Rm18OjxuuWT3AhUeqzq7fHISey2NEEtral/jE7v2Dy59DYHoRAAouWQd02
ZYWnvU5mWoYRcpNmHIj8qk+FOtBWcCGzMZ8uxOxaV74vqqerjxyRI14rXZ+QOcNL
/TMM84h0rl/IKqqWsQIDAQAB
-----END PUBLIC KEY-----
$ cat pubkey_corrupted.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB*QKBgQCkRgRCyTcSwlBKmERQV/BHkurS
5QnYz7Rm18OjxuuWT3A*Ueqzq7fHISey2NEEtral/*E7v2Dy59DYHoRAAouWQd03
ZYWnvU5mWoYRcpNmHIj8q*+FOtBWcCGzMZ8uxOxaV74vqqerjxyRI14rXZ+QOcNM
/TMM84h0rl/IKqqWsQIDAQAB
-----END PUBLIC KEY-----
</code></pre></div></div>
<p>It turns out that <code class="language-plaintext highlighter-rouge">N</code> was corrupted not only in the four <code class="language-plaintext highlighter-rouge">*</code> throughout the file, but additionally the chracaters at the end of the first three lines were also modified… Using the correct pem we find:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="mi">17012713766362055606937340593828012836774345940104644978558327325254454345526470012917476548051189037528193</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">115356776450250827754686976763822189563265178727141719602571509315861796708491086355344129261506721466097001689191320289269213116060519988849918021824941560396659801251826221296538423055226122464968459205865316769204109964482429845998764457962631301677585992875791654646257335269595789163018282966936558671537</span>
<span class="k">print</span><span class="p">(</span><span class="n">gcd</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">n</span><span class="p">))</span>
<span class="c1"># 1546610342396550509721576417620728439706758721827694998050757029568586758684224546628861504368289912502563
</span></code></pre></div></div>
<p>and so our idea was right, but we didnt not understand all the changes. Essentially after factoring <code class="language-plaintext highlighter-rouge">X</code> with msieve, the challenge was to replace all <code class="language-plaintext highlighter-rouge">*</code> and also know to modify the end of each line. If you have any intuition on why this is the case, I would love to know.</p>
<h5 id="flag-7">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{l34Rn_WorK_bY__Msieve__A5aP}</code></p>
<h2 id="dorsa">DoRSA</h2>
<h3 id="challenge-8">Challenge</h3>
<blockquote>
<p>Fun with RSA, this time <a href="https://cr.yp.toc.tf/tasks/DoRSA_17cab1318229a0207b1648615db1edc6497f8b62.txz">two times</a>!</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="kn">from</span> <span class="nn">flag</span> <span class="kn">import</span> <span class="n">FLAG</span>
<span class="k">def</span> <span class="nf">keygen</span><span class="p">(</span><span class="n">nbit</span><span class="p">,</span> <span class="n">dbit</span><span class="p">):</span>
<span class="k">assert</span> <span class="mi">2</span><span class="o">*</span><span class="n">dbit</span> <span class="o"><</span> <span class="n">nbit</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">u</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="n">dbit</span><span class="p">),</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="n">nbit</span> <span class="o">//</span> <span class="mi">2</span> <span class="o">-</span> <span class="n">dbit</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">u</span> <span class="o">*</span> <span class="n">v</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="n">dbit</span><span class="p">),</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="n">nbit</span> <span class="o">//</span> <span class="mi">2</span> <span class="o">-</span> <span class="n">dbit</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">u</span> <span class="o">*</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">q</span><span class="p">)</span> <span class="ow">and</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">r</span><span class="p">):</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">getRandomNBitInteger</span><span class="p">(</span><span class="n">dbit</span><span class="p">)</span>
<span class="k">if</span> <span class="n">gcd</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">u</span> <span class="o">*</span> <span class="n">v</span> <span class="o">*</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">phi</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">r</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">inverse</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">phi</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span> <span class="n">d</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="n">phi</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">k</span> <span class="o">*</span> <span class="n">v</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">isPrime</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="n">n_1</span><span class="p">,</span> <span class="n">n_2</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">r</span><span class="p">,</span> <span class="n">q</span> <span class="o">*</span> <span class="n">s</span>
<span class="k">return</span> <span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">n_1</span><span class="p">,</span> <span class="n">n_2</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">pubkey</span><span class="p">):</span>
<span class="n">e</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="n">pubkey</span>
<span class="k">return</span> <span class="nb">pow</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">nbit</span><span class="p">,</span> <span class="n">dbit</span> <span class="o">=</span> <span class="mi">1024</span><span class="p">,</span> <span class="mi">256</span>
<span class="n">e</span><span class="p">,</span> <span class="n">n_1</span><span class="p">,</span> <span class="n">n_2</span> <span class="o">=</span> <span class="n">keygen</span><span class="p">(</span><span class="n">nbit</span><span class="p">,</span> <span class="n">dbit</span><span class="p">)</span>
<span class="n">FLAG</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">FLAG</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">).</span><span class="nb">hex</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">c_1</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">,</span> <span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">n_1</span><span class="p">))</span>
<span class="n">c_2</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">,</span> <span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">n_2</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">'e ='</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'n_1 ='</span><span class="p">,</span> <span class="n">n_1</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'n_2 ='</span><span class="p">,</span> <span class="n">n_2</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'enc_1 ='</span><span class="p">,</span> <span class="n">c_1</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'enc_2 ='</span><span class="p">,</span> <span class="n">c_2</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>e = 93546309251892226642049894791252717018125687269405277037147228107955818581561
n_1 = 36029694445217181240393229507657783589129565545215936055029374536597763899498239088343814109348783168014524786101104703066635008905663623795923908443470553241615761261684865762093341375627893251064284854550683090289244326428531870185742069661263695374185944997371146406463061296320874619629222702687248540071
n_2 = 29134539279166202870481433991757912690660276008269248696385264141132377632327390980628416297352239920763325399042209616477793917805265376055304289306413455729727703925501462290572634062308443398552450358737592917313872419229567573520052505381346160569747085965505651160232449527272950276802013654376796886259
enc_1 = 4813040476692112428960203236505134262932847510883271236506625270058300562795805807782456070685691385308836073520689109428865518252680199235110968732898751775587988437458034082901889466177544997152415874520654011643506344411457385571604433702808353149867689652828145581610443408094349456455069225005453663702
enc_2 = 2343495138227787186038297737188675404905958193034177306901338927852369293111504476511643406288086128052687530514221084370875813121224208277081997620232397406702129186720714924945365815390097094777447898550641598266559194167236350546060073098778187884380074317656022294673766005856076112637129916520217379601
</code></pre></div></div>
<p>Basically, we have</p>
\[p = uv + 1, \quad q = uy + 1, \quad r = xy + 1, \quad s = kv + 1\]
<p>where $p, q, r, s$ are all primes. Also, $\phi = (p-1)(r-1) = uvxy$ and $ed \equiv 1 \pmod \phi$.
$k$ is calculated by $k = (ed - 1)/\phi$. It is notable that $e$ is $256$ bits.</p>
<p>Our goal is to decrypt RSA-encrypted messages, so we need to find one of $\phi(n_1)$ or $\phi(n_2)$.</p>
<h3 id="solution-8">Solution</h3>
<p>Not so long after starting this problem, rbtree suggested using continued fractions with</p>
\[n_2 / n_1 \approx k / x\]
<p>Indeed, we see that</p>
\[\frac{n_2}{n_1} = \frac{qs}{pr} = \frac{(uy+1)(kv+1)}{(uv+1)(xy+1)} \approx \frac{uykv}{uvxy} = \frac{k}{x}\]
<p>and their difference is quite small, as</p>
\[\frac{n_2}{n_1} - \frac{k}{x} = \frac{(uy+1)(kv+1)x - (uv+1)(xy+1)k}{x(uv+1)(xy+1)}\]
<p>and the numerator is around $256 \times 3$ bits, and the denominator is around $256 \times 5$ bits.</p>
<p>Note that $k/x$ has denominator around 256 bits, and it approximates $n_2/n_1$ with difference around $2^{-512}$. If you know the proof for Wiener’s Attack (highly recommend you study it!) you know that this implies that $k/x$ must be one of the continued fractions of $n_2/n_1$. Now, we can get small number of candidates for $k/x$. We also further assumed $\gcd(k, x) = 1$. If we want to remove this assumption, it is still safe to assume that $\gcd(k, x)$ is a small integer, and brute force all possible $\gcd(k, x)$ as well. Now we have a small number of candidates for $(k, x)$.</p>
<p>I finished the challenge by noticing the following three properties.</p>
<p>First, $k \phi + 1 \equiv 0 \pmod{e}$, so that gives $256$ bit information on $e$.</p>
<p>Second, $\phi \equiv 0 \pmod x$, so that gives another $256$ bit information on $x$.</p>
<p>Finally,</p>
\[|\phi - n_1| = |(p-1)(r-1) - pr| \approx p + r \le 2^{513}\]
<p>Therefore, we can use the first two facts to find $\phi \pmod{ex}$.
Since $ex$ is around $512$ bits, we can get a small number of candidates for $\phi$ using the known bound for $\phi$. If we know $\phi$, we can easily decrypt $c_1$ to find the flag.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span><span class="p">,</span> <span class="n">PKCS1_OAEP</span><span class="p">,</span> <span class="n">PKCS1_v1_5</span>
<span class="kn">from</span> <span class="nn">Crypto.PublicKey</span> <span class="kn">import</span> <span class="n">RSA</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">inverse</span><span class="p">,</span> <span class="n">long_to_bytes</span><span class="p">,</span> <span class="n">bytes_to_long</span><span class="p">,</span> <span class="n">isPrime</span><span class="p">,</span> <span class="n">getPrime</span><span class="p">,</span> <span class="n">GCD</span>
<span class="kn">from</span> <span class="nn">tqdm</span> <span class="kn">import</span> <span class="n">tqdm</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">sage.all</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">itertools</span><span class="p">,</span> <span class="n">sys</span><span class="p">,</span> <span class="n">json</span><span class="p">,</span> <span class="n">hashlib</span><span class="p">,</span> <span class="n">os</span><span class="p">,</span> <span class="n">math</span><span class="p">,</span> <span class="n">time</span><span class="p">,</span> <span class="n">base64</span><span class="p">,</span> <span class="n">binascii</span><span class="p">,</span> <span class="n">string</span><span class="p">,</span> <span class="n">re</span><span class="p">,</span> <span class="n">struct</span><span class="p">,</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">subprocess</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="nn">random</span> <span class="k">as</span> <span class="n">rand</span>
<span class="kn">import</span> <span class="nn">multiprocessing</span> <span class="k">as</span> <span class="n">mp</span>
<span class="kn">from</span> <span class="nn">base64</span> <span class="kn">import</span> <span class="n">b64encode</span><span class="p">,</span> <span class="n">b64decode</span>
<span class="kn">from</span> <span class="nn">sage.modules.free_module_integer</span> <span class="kn">import</span> <span class="n">IntegerLattice</span>
<span class="kn">from</span> <span class="nn">ecdsa</span> <span class="kn">import</span> <span class="n">ecdsa</span>
<span class="k">def</span> <span class="nf">inthroot</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">a</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
<span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">nth_root</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">truncate_mode</span><span class="o">=</span><span class="bp">True</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">phi</span><span class="p">):</span>
<span class="n">tot</span> <span class="o">=</span> <span class="n">n</span> <span class="o">-</span> <span class="n">phi</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">dif</span> <span class="o">=</span> <span class="n">inthroot</span><span class="p">(</span><span class="n">Integer</span><span class="p">(</span><span class="n">tot</span> <span class="o">*</span> <span class="n">tot</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">n</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">dif</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">dif</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="n">tot</span> <span class="o">+</span> <span class="n">dif</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
<span class="n">q</span> <span class="o">=</span> <span class="p">(</span><span class="n">tot</span> <span class="o">-</span> <span class="n">dif</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
<span class="k">if</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span> <span class="o">==</span> <span class="n">n</span><span class="p">:</span>
<span class="k">return</span> <span class="n">p</span><span class="p">,</span> <span class="n">q</span>
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">93546309251892226642049894791252717018125687269405277037147228107955818581561</span>
<span class="n">n_1</span> <span class="o">=</span> <span class="mi">36029694445217181240393229507657783589129565545215936055029374536597763899498239088343814109348783168014524786101104703066635008905663623795923908443470553241615761261684865762093341375627893251064284854550683090289244326428531870185742069661263695374185944997371146406463061296320874619629222702687248540071</span>
<span class="n">n_2</span> <span class="o">=</span> <span class="mi">29134539279166202870481433991757912690660276008269248696385264141132377632327390980628416297352239920763325399042209616477793917805265376055304289306413455729727703925501462290572634062308443398552450358737592917313872419229567573520052505381346160569747085965505651160232449527272950276802013654376796886259</span>
<span class="n">enc_1</span> <span class="o">=</span> <span class="mi">4813040476692112428960203236505134262932847510883271236506625270058300562795805807782456070685691385308836073520689109428865518252680199235110968732898751775587988437458034082901889466177544997152415874520654011643506344411457385571604433702808353149867689652828145581610443408094349456455069225005453663702</span>
<span class="n">enc_2</span> <span class="o">=</span> <span class="mi">2343495138227787186038297737188675404905958193034177306901338927852369293111504476511643406288086128052687530514221084370875813121224208277081997620232397406702129186720714924945365815390097094777447898550641598266559194167236350546060073098778187884380074317656022294673766005856076112637129916520217379601</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">continued_fraction</span><span class="p">(</span><span class="n">Integer</span><span class="p">(</span><span class="n">n_2</span><span class="p">)</span> <span class="o">/</span> <span class="n">Integer</span><span class="p">(</span><span class="n">n_1</span><span class="p">))</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">tqdm</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">150</span><span class="p">)):</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="n">numerator</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="n">denominator</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">if</span> <span class="n">GCD</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">inverse</span><span class="p">(</span><span class="n">e</span> <span class="o">-</span> <span class="n">k</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
<span class="n">cc</span> <span class="o">=</span> <span class="n">crt</span><span class="p">(</span><span class="n">res</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="n">md</span> <span class="o">=</span> <span class="n">e</span> <span class="o">*</span> <span class="n">x</span> <span class="o">//</span> <span class="n">GCD</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="n">st</span> <span class="o">=</span> <span class="n">cc</span> <span class="o">+</span> <span class="p">(</span><span class="n">n_1</span> <span class="o">//</span> <span class="n">md</span><span class="p">)</span> <span class="o">*</span> <span class="n">md</span> <span class="o">-</span> <span class="mi">100</span> <span class="o">*</span> <span class="n">md</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">200</span><span class="p">):</span>
<span class="k">if</span> <span class="n">GCD</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">st</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">st</span> <span class="o">+=</span> <span class="n">md</span>
<span class="k">continue</span>
<span class="n">d_1</span> <span class="o">=</span> <span class="n">inverse</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">st</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">enc_1</span><span class="p">,</span> <span class="n">d_1</span><span class="p">,</span> <span class="n">n_1</span><span class="p">))</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">"CCTF"</span> <span class="ow">in</span> <span class="n">flag</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">st</span> <span class="o">+=</span> <span class="n">md</span>
</code></pre></div></div>
<h5 id="flag-8">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{__Lattice-Based_atT4cK_on_RSA_V4R1aN75!!!}</code></p>
<h2 id="polish">Polish</h2>
<h3 id="challenge-9">Challenge</h3>
<blockquote>
<p>Maybe this time we should focus on important parts of <a href="https://cr.yp.toc.tf/tasks/polish_attack_de0955bc42af9591300a30c39dc74aaceea2451d.txz">RSA</a>!</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">m</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">65537</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="o">=</span> <span class="mi">40246250034008312612597372763167482121403594640959033279625274444300931999548988739160328671767018778652394885185401059130887869211330599272113849088780129624581674441314938139267245340401649784020787977993123159165051168187958742107</span>
<span class="n">d</span> <span class="o">=</span> <span class="mb">0b1</span><span class="p">[</span><span class="n">REDACTED</span><span class="p">]</span><span class="mi">00001101110000010101000000101110000111101011011101111111000011110101111000100001011100001111011000010101010010111100000011000101000001110001111100001011001100010001100000011100001101101100011101000001010001100000101000001</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">m</span> <span class="o">+</span> <span class="n">y</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="o">=</span> <span class="mi">28505561807082805875299833176536442119874596699006698476186799206821274572541984841039970225569714867243464764627070206533293573878039612127495688810559746369298640670292301881186317254368892594525084237214035763200412059090430060075</span>
<span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">*</span> <span class="p">(</span><span class="n">y</span> <span class="o">-</span> <span class="mi">146700196613209180651680280746469710064760660116352037627587109421827052580531</span><span class="p">)</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">2</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="mi">146700196613209180651680280746469710064760660116352037627587109421827052580531</span><span class="p">)</span> <span class="o">=</span> <span class="mi">27617741006445293346871979669264566397938197906017433294384347969002810245774095080855953181508639433683134768646569379922750075630984038851158577517435997971553106764846655038664493024213691627948571214899362078353364358736447296943</span>
</code></pre></div></div>
<p>We have $n$ which we probably need to factor, along with $221$ LSBs of $d$. We also have a diophantine to solve in order to get $x, y$. If we factorize $n$ and find $x, y$, we can compute the flag.</p>
<h3 id="factorization-of-n">Factorization of $n$</h3>
<p>It’s known that with lower $1/4$ bits of $d$, we can factorize $n$ in polynomial time of $e$. To learn how, check out Theorem 9 on <a href="https://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf">Twenty Years of Attacks on the RSA Cryptosystem</a>.</p>
<p>Basically, we can compute $\mathcal{O}(e \log_2 e)$ candidates for the lower half bits of $p$ by solving some quadratic congruences, which we can apply Coppersmith afterwards to factorize $n$.</p>
<h3 id="solving-the-diophantine">Solving the Diophantine</h3>
<p>We start by writing the equation as</p>
\[x^2(y-a) + y^2(x-a) = b\]
<p>To solve this, we substitute</p>
\[u = x+y, \quad v = xy\]
<p>and rewrite our equation as</p>
\[xy(x+y) - a(x^2+y^2) = b \\
uv - a(u^2 - 2v) = b \\
(u+2a) v = au^2 + b \\
v = \frac{au^2 + b}{u + 2a}\]
<p>Performing long division, we see that</p>
\[v = au - 2a^2 + \frac{4a^3 + b}{u + 2a}\]
<p>This shows that $u + 2a$ is a factor of $4a^3 + b$. Therefore, it makes sense to try and factorize $4a^3 + b$ to compute the possible values for $u$.</p>
<p>Surprisingly, it turns out that</p>
\[4a^3 + b = n\]
<p>Now we see that factorization of $n$ solves the problem. Since $n = pq$ has four divisors, we have a small number of candidates for $u+2a$. For each candidate, we can compute $u$, then compute $v$. From $u, v$, we can solve a quadratic to find $x, y$. Then, we can compute the flag.</p>
<h3 id="back-to-factorization-of-n">Back to Factorization of $n$</h3>
<p>rbtree was writing the program to find the factorization of $n$. At first, we $n = pq$ would split evenly, i.e. both $p, q$ would have around $387$ bits.</p>
<p>In this case, after we compute (a candidate of) $221$ LSBs of $p$, we have to find the remaining $166$ MSBs of $p$. To utilize Coppersmith attack, we used SageMath’s small_roots with $\beta = 0.5$ and $\epsilon$ that</p>
<p>\(2^{166} \le \frac{1}{2} n^{\beta^2 - \epsilon}\)
We decided to use $\epsilon = 0.034$ and run the algorithm.</p>
<p>However, while running this algorithm, I suggested that $n = pq$ will not split evenly.</p>
<p>The logic is that one of the factors of $n$ would be $u + 2a$. If we guess that $x$ and $y$ have similar size, we would have something like $x \sim y \sim M$ where $M$ is the value such that</p>
\[2 M^2(M-a) = b\]
<p>Since $b \sim a^3$ we would also have $M \sim a$ which implies $u + 2a \sim a$ as well. Here, $A \sim B$ when $A, B$ have a similar size, i.e. $\max(A, B) / \min(A, B)$ is a small value.</p>
<p>Since $a$ has around $256$ bits, what this means is that $u + 2a$ also has around $256$ bits, i.e. one of $p, q$ has around $256$ bits. Therefore, if our guess is correct, then $n$, which is $773$ bits, is composed of something like $258$ bit $p$ and $515$ bit $q$. This changes how we have to choose $\beta$ and $\epsilon$.</p>
<p>In the end, we have chosen $\beta = 0.33$ and $\epsilon = 0.05$ in the end and ran the algorithm with 20 cores.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Part 1 : Factorization of n, written by rbtree
# Also, multiprocess the code below with multiple cores for shorter computation time
</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">65537</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">40246250034008312612597372763167482121403594640959033279625274444300931999548988739160328671767018778652394885185401059130887869211330599272113849088780129624581674441314938139267245340401649784020787977993123159165051168187958742107</span>
<span class="n">mod</span> <span class="o">=</span> <span class="mi">2</span><span class="o">^</span><span class="mi">221</span>
<span class="n">d_low</span> <span class="o">=</span> <span class="mb">0b00001101110000010101000000101110000111101011011101111111000011110101111000100001011100001111011000010101010010111100000011000101000001110001111100001011001100010001100000011100001101101100011101000001010001100000101000001</span>
<span class="k">def</span> <span class="nf">get_p</span><span class="p">(</span><span class="n">p_low</span><span class="p">):</span>
<span class="n">F</span><span class="p">.</span><span class="o"><</span><span class="n">z</span><span class="o">></span> <span class="o">=</span> <span class="n">PolynomialRing</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">mod</span> <span class="o">*</span> <span class="n">z</span> <span class="o">+</span> <span class="n">p_low</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">monic</span><span class="p">()</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">small_roots</span><span class="p">(</span><span class="n">beta</span><span class="o">=</span><span class="mf">0.33</span><span class="p">,</span> <span class="n">epsilon</span><span class="o">=</span><span class="mf">0.05</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">res</span><span class="p">)</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">return</span> <span class="bp">None</span>
<span class="n">R</span><span class="p">.</span><span class="o"><</span><span class="n">x</span><span class="o">></span> <span class="o">=</span> <span class="n">PolynomialRing</span><span class="p">(</span><span class="n">ZZ</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">e</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="n">cands</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">k</span> <span class="o">*</span> <span class="n">x</span><span class="o">^</span><span class="mi">2</span> <span class="o">+</span> <span class="p">(</span><span class="n">e</span><span class="o">*</span><span class="n">d_low</span> <span class="o">-</span> <span class="n">k</span><span class="o">*</span><span class="n">n</span> <span class="o">-</span> <span class="n">k</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="n">k</span> <span class="o">*</span> <span class="n">n</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">221</span><span class="p">):</span>
<span class="n">new_cands</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">cands</span><span class="p">:</span>
<span class="k">if</span> <span class="n">f</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span><span class="o">^</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">new_cands</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="k">if</span> <span class="n">f</span><span class="p">(</span><span class="n">v</span> <span class="o">+</span> <span class="mi">2</span><span class="o">^</span><span class="n">i</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span><span class="o">^</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">new_cands</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">v</span> <span class="o">+</span> <span class="mi">2</span><span class="o">^</span><span class="n">i</span><span class="p">)</span>
<span class="n">cands</span> <span class="o">=</span> <span class="n">new_cands</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">new_cands</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"break"</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">print</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">cands</span><span class="p">)</span>
<span class="n">ret</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">for</span> <span class="n">v1</span> <span class="ow">in</span> <span class="n">cands</span><span class="p">:</span>
<span class="k">for</span> <span class="n">v2</span> <span class="ow">in</span> <span class="n">cands</span><span class="p">:</span>
<span class="k">if</span> <span class="n">v1</span> <span class="o">*</span> <span class="n">v2</span> <span class="o">%</span> <span class="n">mod</span> <span class="o">!=</span> <span class="n">n</span> <span class="o">%</span> <span class="n">mod</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">get_p</span><span class="p">(</span><span class="n">v1</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">if</span> <span class="n">ret</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">print</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span>
<span class="k">if</span> <span class="n">ret</span><span class="p">:</span>
<span class="k">break</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Part 2 : Calculating the Flag
</span>
<span class="k">def</span> <span class="nf">inthroot</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">nth_root</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">truncate_mode</span><span class="o">=</span><span class="bp">True</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">40246250034008312612597372763167482121403594640959033279625274444300931999548988739160328671767018778652394885185401059130887869211330599272113849088780129624581674441314938139267245340401649784020787977993123159165051168187958742107</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">146700196613209180651680280746469710064760660116352037627587109421827052580531</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">27617741006445293346871979669264566397938197906017433294384347969002810245774095080855953181508639433683134768646569379922750075630984038851158577517435997971553106764846655038664493024213691627948571214899362078353364358736447296943</span>
<span class="k">assert</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">a</span> <span class="o">*</span> <span class="n">a</span> <span class="o">*</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
<span class="c1"># from rbtree's code with partial exposure attack on d
</span><span class="n">p</span> <span class="o">=</span> <span class="mi">893797203302975694226187727100454198719976283557332511256329145998133198406753</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="n">p</span>
<span class="n">u</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">a</span>
<span class="n">v</span> <span class="o">=</span> <span class="p">(</span><span class="n">a</span> <span class="o">*</span> <span class="n">u</span> <span class="o">*</span> <span class="n">u</span> <span class="o">+</span> <span class="n">b</span><span class="p">)</span> <span class="o">//</span> <span class="p">(</span><span class="n">u</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">a</span><span class="p">)</span>
<span class="n">dif</span> <span class="o">=</span> <span class="n">inthroot</span><span class="p">(</span><span class="n">Integer</span><span class="p">(</span><span class="n">u</span> <span class="o">*</span> <span class="n">u</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">v</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">u</span> <span class="o">+</span> <span class="n">dif</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="n">u</span> <span class="o">-</span> <span class="n">dif</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">65537</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">28505561807082805875299833176536442119874596699006698476186799206821274572541984841039970225569714867243464764627070206533293573878039612127495688810559746369298640670292301881186317254368892594525084237214035763200412059090430060075</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">inverse</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">res</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">res</span> <span class="o">-</span> <span class="n">x</span> <span class="o">*</span> <span class="n">x</span> <span class="o">-</span> <span class="n">y</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">res</span> <span class="o">-</span> <span class="n">y</span> <span class="o">*</span> <span class="n">y</span> <span class="o">-</span> <span class="n">x</span><span class="p">))</span>
</code></pre></div></div>
<h5 id="flag-9">Flag</h5>
<p><code class="language-plaintext highlighter-rouge">CCTF{Par7ial_K3y_Exp0sure_At7ack_0n_L0w_3xP_RSA}</code></p>["CryptoHackers"]Last week, CryptoHackers got together to play CryptoCTF for the second time as a team. We solved 26/29 of the challenges during the 24 hour window and came third overall. First and second places went to Super Guessers (Rkm and Rbtree are very friendly faces from CryptoHack) and a Vietnamese team working together to support the spirit of Ho Chi Minh city and nearby provinces. Congratulations to them both.New Challenges 06/20212021-06-24T00:00:00+00:002021-06-24T00:00:00+00:00https://blog.cryptohack.org/new-challenges-june-2021<p>Hello CryptoHackers! This week we’ll be releasing a new set of challenges, mostly made up of great community submissions. But first, a quick recap of what we’ve been up to in our mission to spread cryptography knowledge.</p>
<p>The main thing we’ve done recently was team up with HackTheBox for <a href="https://ctftime.org/event/1304">Cyber Apocalypse CTF 2021</a>. We worked hard to write challenges which were fun and accessible for all players. We made detailed walkthroughs for them <a href="/cyber-apocalypse-2021">here</a>. A huge number of players solved at least a few of these challenges, and we hope we’ve infected many new players with our love of cryptography!</p>
<p>As a community, we had our biggest success on social media yet with the blog post <a href="/twitter-secrets">“Recovering a full PEM Private Key when half of it is redacted”</a>. This was a fun effort from many people in the chat and was discussed on <a href="https://twitter.com/CryptoHack__/status/1374758520642531331">Twitter</a>, <a href="https://old.reddit.com/r/netsec/comments/mcar4f/recovering_a_whole_pem_private_key_when_half_of/">Reddit</a>, and several security newsletters.</p>
<p>We’re also collaborating with the <a href="https://isogenyschool2020.co.uk">Isogeny School</a>, organised by Chloe Martindale and Christophe Petit, to create and share a set of dynamic exercises and CTF-like puzzles to support the virtual learning programme on isogeny-based cryptography. <a href="https://isogenyschool2020.co.uk/register/">Registration</a> for the school is open now and will run between July-September 2021.</p>
<p>Finally, in terms of the chat, Jack has been running a reading group looking at a different famous cryptography paper each week. We also brought on Robin Jadoul to the admin team; his patience in answering the questions of newcomers and in sharing his huge knowledge has been a big part of what’s made the CryptoHack Discord such an awesome community.</p>
<p>We would like to thank our Patreons for continued support. Our next goal is to reorganise the website in response to feedback we’ve received. For a start, unlike they way it started, the “block ciphers” / “AES” section now contains plenty of ciphers which are neither block ciphers nor AES! We will update all this content and also restructure it into more manageable chunks to make the learning experience better.</p>
<h3 id="new-challenge-descriptions">New Challenge Descriptions</h3>
<ul>
<li><strong>SSH Keys</strong> (Data Formatting): Easy challenge that has a brief intro to SSH and describes how the keys are formatted.</li>
<li><strong>Roll Your Own</strong> (Maths Brainteasers): Discrete logarithms seem like a great foundation for building a public key cryptosystem, what could go wrong? <em>Contributed by mystiz</em></li>
<li><strong>Dancing Queen</strong> (Symmetric Ciphers): Daniel Bernstein’s next generation ciphers like ChaCha and Salsa are often praised for being more misuse-resistant compared to what came before. But are they resistant to being implemented incorrectly? <em>Contributed by yaumn and Synacktiv</em></li>
<li><strong>The Matrix Trilogy</strong> (Diffie-Hellman) a set of three Diffie-Hellman Key exchange challenges which focus on studying matrices over finite fields. <em>Contributed by Jschnei</em></li>
<li><strong>Montgomery’s Ladder</strong> (ECC): This challenge kicks off a side channel attack stage for Elliptic Curve Cryptography, with a nice tutorial. Side channel attacks are a big concern of modern cryptography and something we’d like to explore more on CryptoHack.</li>
<li><strong>Double and Broken</strong> (ECC): Similar to the previous challenge, we can’t say much more without giving the game away (perhaps the title already does)</li>
<li><strong>Hash Stuffing</strong> (Hashing): Can you cause a collision in a simple custom hashing function?</li>
<li><strong>LFSR Destroyer</strong> (LFSRs): Adding to Cryptanalyse’s set teaching how to break LFSRs, is a challenge based on a similar construction to the GEA algorithms that were recently suggested to be deliberately backdoored. <em>Contributed by Cryptanalyse</em></li>
<li><strong>RSA or HMAC Part 2</strong> (Crypto on the Web): Here’s another JWT challenge, a trick which involves a little more work than the previous ones.</li>
</ul>
<h3 id="current-scoreboard">Current scoreboard</h3>
<p><img src="/assets/images/scoreboard_202106.png" alt="CryptoHack Scoreboard 2021/06" /></p>
<p>Congratulations to ndh, rkm0959, and pcback for solving the last set of challenges the fastest.</p>hyperreality and JackHello CryptoHackers! This week we’ll be releasing a new set of challenges, mostly made up of great community submissions. But first, a quick recap of what we’ve been up to in our mission to spread cryptography knowledge.