<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: skaunov</title>
    <description>The latest articles on Forem by skaunov (@skaunov).</description>
    <link>https://forem.com/skaunov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F932392%2F48d2c012-8da4-4a78-9ecf-580178966f69.jpeg</url>
      <title>Forem: skaunov</title>
      <link>https://forem.com/skaunov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/skaunov"/>
    <language>en</language>
    <item>
      <title>Cryptopals-57 solution</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Fri, 13 Feb 2026 14:59:47 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-57-solution-21m4</link>
      <guid>https://forem.com/skaunov/cryptopals-57-solution-21m4</guid>
      <description>&lt;p&gt;Cryptopals is a least priority thing I'm enjoying somewhat consistently; hence it has crazy lags. &lt;a href="https://dev.to/skaunov/cryptopals-set-7-in-rust-11ef"&gt;I started #8 in 2024&lt;/a&gt; and here it is; every time I opened the file with the code it was like someone you knew long ago and now hardly recognize. But that's quite an exercise (and maybe a skill) too. That explains why the code sometimes looks funny even to myself; but if I take the time to groom it further I will just never finish as I progress as a developer more often than I open the file. Another explanation needed is about some mistakes preserved in the comments: primarily this code is for me to reflect when I stumble onto it later, and those help me to follow &amp;amp; recollect the things. It doesn't look like I will finish the set, but #57 is here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;num_bigint&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RandBigInt&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;num_traits&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;One&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Zero&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
    &lt;span class="nn"&gt;rngs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nn"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SliceRandom&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"4565356397095740655436854503483826832136106141639563487732438195343690437606117828318042418238184896212352329118608100083187535033402010599512641674644143"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"236234353446506858198510045061214171961"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;biguint_from_str_decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;BigUint&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_str_radix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;one&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;biguint_from_str_decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"7199773997391911030609999317773941274322764333428698921736339643928346453700085358802973900485592910475480089726140708102474957429903531369589969318716771"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the number of bits `p` takes:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="nf"&gt;.bits&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;biguint_from_str_decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"30477252323177606811760882179058908038824640750610513771646768011063128035873508507547741559514324673960576895059570"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;biguint_from_str_decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;biguint_from_str_decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the number of bits `q` takes:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="nf"&gt;.bits&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* 
    &amp;gt; You don't need to factor it all the way. Just find a bunch of factors
    smaller than, say, 2^16. There should be plenty. (Friendly tip: maybe
    avoid any repeated factors. They only complicate things.) */&lt;/span&gt;
    &lt;span class="cm"&gt;/* During debugging I took the advice on the small 
    factors. Until then I went with `HashMap`, and created 
    it `from([2])` (which wasn't the bright idea from a few 
    angles). 
    The logic was that doesn't participate in other small 
    factors, so "let's just add it here".

    I wanted to go the complicated case to play with the 
    degree of each factor. But due to a mistake I had to 
    debug, I just checked that starting from $329$ all the 
    factors are degree $1$, and switched to `HashSet` 
    starting from that number to not change the code I've 
    already debugged. Not taking the suggested short-cut 
    should be an educatory refresher on CRT. 

    I didn't thought though that I brutely sieve here and 
    starting factoring from a number after the 
    tiny/repeating factors will introduce additional 
    factors (here it's one) which absorbs those repeating 
    and brings all the complications we were adviced to 
    avoid. So it's easier to sieve properly; 
    but then repeating factors are still dropped. */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;factoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="cm"&gt;/* obvious optimization is replace the range for 
    the primes; then drop `rayon` in */&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;2usize&lt;/span&gt;&lt;span class="nf"&gt;.pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;factoring&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="nf"&gt;.entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.or_default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="c1"&gt;// with `HashSet` it was the following&lt;/span&gt;
            &lt;span class="c1"&gt;// let _new = factors.insert(m);&lt;/span&gt;
            &lt;span class="c1"&gt;// debug_assert!(_new);&lt;/span&gt;

            &lt;span class="n"&gt;factoring&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;factors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.filter_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;|(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;degree&lt;/span&gt;&lt;span class="p"&gt;)|&lt;/span&gt; 
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;degree&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} factors will be used:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* 
    &amp;gt; ...we can use these to recover Bob's secret key using
    the Pohlig-Hellman algorithm for discrete logarithms... */&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bob_key_priv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="cm"&gt;/* Actually it doesn't make sense to care about drawing 
    the zero since it's plainly improbable, but this is the 
    exclusion thing I still do; in the end of the day let's 
    hope the secret is a non-zero type. Earlier challenges 
    show that a correct way is to generate everything and 
    then check zero (in fact all trivial/special cases) 
    specifically. */&lt;/span&gt;
    &lt;span class="c1"&gt;// .gen_biguint_below(&amp;amp;p)&lt;/span&gt;
    &lt;span class="nf"&gt;.gen_biguint_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="cm"&gt;/* Continuing the previous note, this exclusion 
        always was mostly a joke or over caution; it was 
        cute to see I did this more than an year ago, and 
        just recently asked in a randomness dedicated group 
        if this ever makes any sense: they just reassured it 
        does not! */&lt;/span&gt;
        &lt;span class="c1"&gt;// &amp;amp;BigUint::from(2u8).pow(80), &lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="cm"&gt;/* To me this is an interesting part of the 
        exercise! It designed so that the key is taken from 
        `q` which makes sense if think about it. But the 
        exercise is an opportunity to try what would happen 
        if we draw from `p`. Usually it's not that 
        interesting since an EC group would have a handful
        of small order subgroups which without cofactor 
        clearance will be cycling pretty quick. But here we 
        have 512-bit field with somewhat sizeable factors. 
        #drawFromP */&lt;/span&gt;
        &lt;span class="c1"&gt;// &amp;amp;p&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* I guess over `q` I could try an arithmetic 
    MAC algorithm in this exercise. :notsure: */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_bob_key_pub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="nf"&gt;.modpow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bob_key_priv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="cm"&gt;/* At some point I got confused in experimentaion. 
        #modulusConfusion #drawFromP */&lt;/span&gt;
        &lt;span class="c1"&gt;// &amp;amp;q&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// assert_eq!(_bob_key_pub, g.modpow(&lt;/span&gt;
    &lt;span class="c1"&gt;//     &amp;amp;bob_key_priv, &lt;/span&gt;
    &lt;span class="c1"&gt;//     &amp;amp;q&lt;/span&gt;
    &lt;span class="c1"&gt;// ));&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;k_guess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* 
        &amp;gt; 1. Take one of the small factors j. Call it r. We want to find an
        element h of order r. ... */&lt;/span&gt;
        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r_cofactor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;r_cofactor&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* it's like cofactor clearing but for 
            a tiny factor instead of a proper */&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.gen_biguint_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.modpow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;r_cofactor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; 
                &lt;span class="c1"&gt;// dbg!(&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;
                &lt;span class="c1"&gt;// ) &lt;/span&gt;
                &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt; 
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="nf"&gt;.modpow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="s"&gt;"we must be in a subgroup `r`"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="cm"&gt;/* 
        &amp;gt; 2. You're Eve. Send Bob h as your public key. Note that h is not a
        valid public key! There is no x such that h = g^x mod p. ... */&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;eve_key_pub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="cm"&gt;/* 
        &amp;gt; 3. Bob will compute:
        &amp;gt; 
        &amp;gt;    K := h^x mod p
        &amp;gt; 
        &amp;gt; Where x is his secret key and K is the output shared secret. Bob
        then sends back (m, t), with:
        &amp;gt; 
        &amp;gt;    m := "crazy flamboyant for the rap enjoyment"
        t := MAC(K, m) */&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bob_key_priv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eve_key_pub&lt;/span&gt;&lt;span class="nf"&gt;.modpow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;
            &lt;span class="c1"&gt;// #modulusConfusion&lt;/span&gt;
            &lt;span class="c1"&gt;// &amp;amp;q&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;the&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="cm"&gt;/* 
        &amp;gt;  4. ...
        &amp;gt; 
        &amp;gt; ...there are only r possible values
    of K that Bob could have generated. We can recover K by doing a
    brute-force search over these values until t = MAC(K, m). */&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;k_guessed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// could fail on additive identity, but we have kind of protection while drawing (instead of with types)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// subgroup size should be $r-1$&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;the&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k_guessed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;k_guessed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k_guessed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                &lt;span class="c1"&gt;// #modulusConfusion&lt;/span&gt;
                &lt;span class="c1"&gt;// % &amp;amp;q;&lt;/span&gt;
                &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// let k_guessed = (0..r).into_par_iter().position_any(|guess| {&lt;/span&gt;
        &lt;span class="c1"&gt;//     &amp;amp;mac(&amp;amp;h.modpow(&amp;amp;guess.into(), &amp;amp;p)) == &amp;amp;t&lt;/span&gt;
        &lt;span class="c1"&gt;// }).unwrap();&lt;/span&gt;
        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;the&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k_guessed&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
            &lt;span class="s"&gt;"step &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;4.&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt; encountered a problem with `r`:{}, `x`:{}, `t`:{:?}, `x % r`:{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// let x_mod_r = (0..r).into_par_iter().position_any(&lt;/span&gt;
        &lt;span class="c1"&gt;//     |i| &amp;amp;k_guessed == &amp;amp;h.modpow(&amp;amp;i.try_into().unwrap(), //&amp;amp;r.into())&lt;/span&gt;
        &lt;span class="c1"&gt;// ).unwrap();&lt;/span&gt;
        &lt;span class="cm"&gt;/* degree of $h$ when it becomes equal to K */&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x_mod_r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;h_runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x_runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k_guessed&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;h_runner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;x_runner&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;h_runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h_runner&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                    &lt;span class="c1"&gt;// #modulusConfusion&lt;/span&gt;
                    &lt;span class="c1"&gt;// % &amp;amp;q;&lt;/span&gt;
                    &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="n"&gt;x_runner&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{r} was chosen as another factor"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(x_mod_r);&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(&amp;amp;bob_key_priv % r);&lt;/span&gt;
        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_mod_r&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
            &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bob_key_priv&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k_guessed&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;r_cofactor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_mod_r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="cm"&gt;/* 
    &amp;gt; 5. ... */&lt;/span&gt;
    &lt;span class="c1"&gt;// let mut factors = factors.into_iter();&lt;/span&gt;
    &lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="nf"&gt;.shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;accumulated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;kk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;accumulated&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="nf"&gt;.pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;k_guess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
        &lt;span class="n"&gt;accumulated&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// &amp;gt; ...reassemble Bob's secret key using the Chinese Remainder Theorem.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;product_factors_chosen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)|&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="py"&gt;.product&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bob_key_priv_guessed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;|(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_cofactor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_mod_factor&lt;/span&gt;&lt;span class="p"&gt;))|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cofactor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;product_factors_chosen&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="c1"&gt;// dbg!(&lt;/span&gt;
                &lt;span class="n"&gt;x_mod_factor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cofactor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;cofactor&lt;/span&gt;&lt;span class="nf"&gt;.modinv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// )&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// .reduce(&amp;lt;BigUint as core::ops::Add&amp;gt;::add)).unwrap()&lt;/span&gt;
    &lt;span class="py"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BigUint&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;product_factors_chosen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// #drawFromP&lt;/span&gt;
    &lt;span class="c1"&gt;// let mut bob_key_priv_guessed = bob_key_priv_guessed % &amp;amp;p;&lt;/span&gt;
    &lt;span class="c1"&gt;// while dbg!(&amp;amp;bob_key_priv_guessed) &amp;gt;= &amp;amp;p {bob_key_priv_guessed *= bob_key_priv_guessed.clone();}&lt;/span&gt;

    &lt;span class="nd"&gt;debug_assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_key_priv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bob_key_priv&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// dbg!(dbg!(&amp;amp;bob_key_priv % &amp;amp;q) == dbg!(&lt;/span&gt;
    &lt;span class="c1"&gt;//     dbg![&amp;amp;bob_key_priv_guessed]&lt;/span&gt;
    &lt;span class="c1"&gt;//         // .modpow(&amp;amp;j, &amp;amp;p)&lt;/span&gt;
    &lt;span class="c1"&gt;//         % &amp;amp;q&lt;/span&gt;
    &lt;span class="c1"&gt;// ));&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the Private key"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bob_key_priv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// let variants_left = factors_cloned.into_iter().fold(p / q, |dived, factor| dived / factor);&lt;/span&gt;
    &lt;span class="c1"&gt;// dbg!(variants_left);&lt;/span&gt;

    &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_key_priv&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;bob_key_priv_guessed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The private key have been guessed correctly."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// a tiny remnant I decided to keep of an experiment&lt;/span&gt;
    &lt;span class="c1"&gt;// let bob_key_pub = mac(&amp;amp;bob_key_priv);&lt;/span&gt;
    &lt;span class="c1"&gt;// if bob_key_pub == mac(&amp;amp;bob_key_priv_guessed) {println!("CORRECT");}&lt;/span&gt;
    &lt;span class="c1"&gt;// else {println!("guessing FAILED");}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cd"&gt;/// I remember I wanted to try something I either won't as &lt;/span&gt;
&lt;span class="cd"&gt;/// MAC is absolutely lateral here -- main point is just &lt;/span&gt;
&lt;span class="cd"&gt;/// grind the value out of a small set of possible. But to &lt;/span&gt;
&lt;span class="cd"&gt;/// play with 512-bit numbers and when I had a mistake in &lt;/span&gt;
&lt;span class="cd"&gt;/// the core thing I settled here with the most boring &lt;/span&gt;
&lt;span class="cd"&gt;/// variant. Still, again, this doesn't impact anything.&lt;/span&gt;
&lt;span class="cd"&gt;/// &lt;/span&gt;
&lt;span class="cd"&gt;/// The options I considered for fun were quite different &lt;/span&gt;
&lt;span class="cd"&gt;/// to see another approaches.&lt;/span&gt;
&lt;span class="cd"&gt;/// https://docs.rs/cmac/latest/cmac/struct.CmacCore.html&lt;/span&gt;
&lt;span class="cd"&gt;/// https://docs.rs/dbl/0.3.2/dbl/trait.Dbl.html&lt;/span&gt;
&lt;span class="cd"&gt;/// https://docs.rs/threefish/latest/threefish/struct.Threefish512.html&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
        &lt;span class="nn"&gt;consts&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;U32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;generic_array&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GenericArray&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;Mac&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;the&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
        &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;num_bigint&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BigUint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="c1"&gt;// m: &amp;amp;[u8]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt;  &lt;span class="n"&gt;GenericArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;U32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="cm"&gt;/* BigUint */&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="c1"&gt;// let k = k % &amp;amp;p;&lt;/span&gt;
        &lt;span class="c1"&gt;// let mut t = &lt;/span&gt;
        &lt;span class="c1"&gt;//     &amp;lt;blake2::Blake2bMac::&amp;lt;blake2::digest::consts::U64&amp;gt; as blake2::digest::Mac&amp;gt;::new_from_slice(&amp;amp;k.to_bytes_le()).unwrap();&lt;/span&gt;
        &lt;span class="c1"&gt;// blake2::digest::Update::update(&amp;amp;mut t, m);&lt;/span&gt;
        &lt;span class="c1"&gt;// blake2::digest::Mac::finalize(t).into_bytes().to_vec()&lt;/span&gt;

        &lt;span class="c1"&gt;// g.modpow(k, &amp;amp;p)&lt;/span&gt;

        &lt;span class="c1"&gt;// let k = k % &amp;amp;q; // 128 bits&lt;/span&gt;
        &lt;span class="c1"&gt;// let k_bytes = &amp;amp;k.to_bytes_le();&lt;/span&gt;
        &lt;span class="c1"&gt;// let k_bytes = &lt;/span&gt;
        &lt;span class="c1"&gt;//     [k_bytes.as_slice(), &amp;amp;[0].repeat(16 - k_bytes.len())].concat();&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(k_bytes.len());&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Hmac&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;sha2&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sha256&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;
        &lt;span class="nf"&gt;new_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="nf"&gt;.to_bytes_le&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.as_slice&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"crazy flamboyant for the rap enjoyment"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="nf"&gt;.finalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into_bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>rust</category>
      <category>cryptopals</category>
    </item>
    <item>
      <title>_$t$ out of $n$_ with `dcipher` and without</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Sun, 10 Aug 2025 10:57:03 +0000</pubDate>
      <link>https://forem.com/skaunov/t-out-of-n-with-dcipher-and-without-19he</link>
      <guid>https://forem.com/skaunov/t-out-of-n-with-dcipher-and-without-19he</guid>
      <description>&lt;p&gt;Listeners of &lt;a href="https://www.youtube.com/playlist?list=PLsg1px0GrGgi3pIBneYkhTk8t-W26rMs1" rel="noopener noreferrer"&gt;Threshold Cryptography Bootcamp&lt;/a&gt; were (t)asked to reflect on the first four sessions we got to this date. I guess the most of approaches to the task will be a (LLM-)conspect of the lectures, and I don't want to join this chorus since there's quite a number of threshold crypto guides and I can only produce a worse one. Instead let me think out loud on &lt;strong&gt;comparison of the threshold approach and naive multisig.&lt;/strong&gt; I mean the nature of the lectures advertises the first one quite heavily and as a natural (for a cryptography engineer) skeptic push-back I was constantly tried to think how the things could be done (and often are done currently) without thresholds.&lt;/p&gt;

&lt;p&gt;By multisig I mean just counting the signatures on something which obviously can solve the very same problem: &lt;em&gt;to require $t$ out of $n$&lt;/em&gt; sign-offs before going. My current conclusion (probably wrong as I'm just get the feeling of the things) is that thresholds are really superior in the two aspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they're much cheaper in the sense they takes both the size and verification computation of &lt;strong&gt;one&lt;/strong&gt; signature; and&lt;/li&gt;
&lt;li&gt;they're &lt;strong&gt;deterministic&lt;/strong&gt; which enables a lot of interesting directions to explore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They have their problems too. The committee (the $n$ out of which we need $t$ sigs) is one way or another is gated and need to go through a fancy procedure to keep the determinism when it changes, and there's not much we know to do now to prevent colluding or just (silently) leaking/loosing their key by a member (i.e. $1$ out of $n$) which leads us to strong or weak but inevitable assumption of some honesty of a committee (which mostly explains its gated nature/requirement). That's was a summary &amp;amp; conclusions, and further I'll try to unpack this with more lengthy thought on these points.&lt;/p&gt;

&lt;p&gt;A lot of emphasize was put on BLS signature scheme during the lecture as a corner-stone of threshold cryptography. If I get this correctly it's because the sigs are homomorphic (but not &lt;em&gt;fully&lt;/em&gt;; for that they'd need this property over multiplication as well). Okay, we can sum a batch of sigs and the result is the valid (aggregated) sig on the thing. Sounds useful for multisig as well!&lt;/p&gt;

&lt;p&gt;I feel that &lt;em&gt;$t$ out of $n$&lt;/em&gt; problem is hairy either on the initial end or on the final end; and it's the insight or way to look at the problem of this write-up. Multisig approach lean to be hairy in the finish, and threshold approach leans to be hairy on the start (but there are good news to it below - spoiler #standardization). Btw, it's a reason why multisig is "naive" here: it's easy to start with just the primitives you already have and count the sigs until there are $t$ of those. But further we go with it -- more challenges to solve we get: remembering the sigs (or the fact of verification), management of the committee membership, time to verify or parallelization and trust in this process. All these problems are solvable, and multisig itself isn't naive when done sophisticated, &lt;strong&gt;but anyway&lt;/strong&gt; the solution of the problems are in the end of a thing, closer to when verification happens; and the size is something which can't be workaround without loosing verifiability.&lt;/p&gt;

&lt;p&gt;Let's briefly get over the main moving parts to better appreciate the benefit(s) of a threshold approach.&lt;/p&gt;

&lt;p&gt;I just came up with &lt;em&gt;committee key&lt;/em&gt; but I feel it's a descriptive term! Also the diagram source is available in the end of the page.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjetfl97o89wgk8q646w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjetfl97o89wgk8q646w.png" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[! A fun insight I got]&lt;br&gt;
All the VRF and everything else is just something a committee signs in the same way. Just give them instead of the &lt;em&gt;generator&lt;/em&gt; a specific value which represents something you need (timestamp, block height, some data - all will be hashed to the curve anyway) and &lt;strong&gt;sign&lt;/strong&gt; in the same fashion --- the resulted point is that deterministic piece of data you will be building upon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A single public key sounds like a miracle, it's a huge enabler indeed! But what if the committee needs to be changed (and here goes all the other challenges mentioned earlier for multisig)? The answer is that we need to preserve the polynomial which defines the key during all the manipulations. And it's at least as hairy as the other approach, but now it should be dealt before we get to signing anything --- that's why I present it as the other end of the process. We need to do quite complex protocols (which are still advances rapidly; see &lt;em&gt;distributed key generation&lt;/em&gt; - it's the main rabbit hole here) &lt;strong&gt;before&lt;/strong&gt; getting to sign things, but then we have nice, clean, and deterministic system in our hands. Why determinism here such a great deal? It enables of the thing with "auto-": auto-reveal, auto-decryption, auto-confirmation, and so on. Because while multisig is busy with its hairy stuff threshold approach has one stage less on the finish and doesn't need an additional interactions thanks to using that known public key defined by the polynomial (multisig never knows which members come up with signatures in the end of the day, so after sign-off another action is needed).&lt;/p&gt;

&lt;p&gt;I nearly abused the word "hairy" today, but let's end this with a major note. What's appealing to me &lt;code&gt;dcipher&lt;/code&gt; (personally I think &lt;code&gt;tcipher&lt;/code&gt; would be a cuter name) do the #standardization effort so that we could have nice and clean abstraction on the initial end of the threshold approach as well. I guess it's a process, and not all the standards catch-up immediately especially when the domain pace is high (👋 &lt;a href="https://zkproof.org/" rel="noopener noreferrer"&gt;https://zkproof.org/&lt;/a&gt;), but I feel that all these efforts are not in vain and helps us even when a next effort overcome the current wave. Let's "stand on the shoulders of giants!"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph LR
    subgraph Threshold_t["any $t$ out of $n$ keys are sufficient"]
        A[Personal Key 1] --&amp;gt;|Contains| P[Polynomial of Degree $t-1$]
        B[Personal Key 2] --&amp;gt;|Contains| P
        C[Personal Key t] --&amp;gt;|Contains| P
    end
    D[Personal Key t+1] --&amp;gt;|Contains| P
    E[Personal Key n] --&amp;gt;|Contains| P
    P --&amp;gt;|Defines| CK[Committee Key]
    CK --&amp;gt;|Signs| G[the Generator]
    G --&amp;gt;|Produces| PK[Deterministic Public Key]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Cryptopals set 8 in Rust</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Thu, 14 Mar 2024 18:43:56 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-set-7-in-rust-11ef</link>
      <guid>https://forem.com/skaunov/cryptopals-set-7-in-rust-11ef</guid>
      <description>&lt;p&gt;As I led my current things to some milestones, and now I mostly reading about folding and prove systems I have some time to return to Cryptopals. Quick search doesn't yield Rust solutions to the last set --- add a link, pls, if you know them published somewhere.&lt;/p&gt;

&lt;p&gt;(Here's the current things, btw.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/plume-sig/zk-nullifier-sig/pull/104" rel="noopener noreferrer"&gt;https://github.com/plume-sig/zk-nullifier-sig/pull/104&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lambdaclass/lambdaworks/pull/838" rel="noopener noreferrer"&gt;https://github.com/lambdaclass/lambdaworks/pull/838&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bisq-network/growth/issues/288#issuecomment-1905566355" rel="noopener noreferrer"&gt;https://github.com/bisq-network/growth/issues/288#issuecomment-1905566355&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the best effort basis I will be adding code here, and maybe some notes if a better writings won't jump to me from some page. Usual stuff.&lt;/p&gt;

&lt;p&gt;If you have any comments or ideas to this you're welcome to express it in the comments. This is just kind of an announcement dedicated to this purpose. Cheers!&lt;/p&gt;

</description>
      <category>cryptopals</category>
      <category>rust</category>
    </item>
    <item>
      <title>Cryptopals #51 in Rust</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Fri, 08 Dec 2023 00:28:19 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-51-in-rust-1igl</link>
      <guid>https://forem.com/skaunov/cryptopals-51-in-rust-1igl</guid>
      <description>&lt;p&gt;This one turned out to be haunting for me. I started it and had so many more priority things which postponed it (no jokes - start it a year ago). And like most of the things which didn't receive proper treatment I can't say it's done well. Though it's better to put the dot in the story of this one.&lt;/p&gt;

&lt;p&gt;As usual I even posting it because I didn't really seen the solution in Rust when I was looking for it. Because it would be cool if someone would show where I did a mistake (is it ChaCha, or padding, or DEFLATE?). And there's a lot of comments/snippets to track how I was thinking during the time I've spent on this one. (The code itself in the end of the text.)&lt;/p&gt;

&lt;p&gt;I somehow omitted CTR part and started right from CBC.&lt;/p&gt;

&lt;p&gt;There's number of good descriptions of the solution out there. I particularly liked &lt;a href="https://raywang.tech/2017/09/11/matasano-crypto-challenges-set-7/#challenge-51-compression-ratio-side-channel-attacks-aka-crime" rel="noopener noreferrer"&gt;writeup&lt;/a&gt;; also really good and helpful are &lt;a href="https://docs.google.com/presentation/d/11eBmGiHbYcHR9gL5nDyZChu_-lCa2GizeuOfaLU2HOU/" rel="noopener noreferrer"&gt;slides&lt;/a&gt; from CRIME authors.&lt;/p&gt;

&lt;p&gt;I've made &lt;em&gt;all&lt;/em&gt; the wrong moves described in the &lt;a href="https://raywang.tech/2017/09/11/matasano-crypto-challenges-set-7/#challenge-51-compression-ratio-side-channel-attacks-aka-crime" rel="noopener noreferrer"&gt;writeup&lt;/a&gt;. And I stopped finding 20 strings (including the solution), which is the reason of having that 'gestalt' and some following scattered notes on possible reasons of that.&lt;/p&gt;

&lt;p&gt;I guess it's possible to find sweet-spot of CBC &lt;em&gt;and&lt;/em&gt; DEFLATE boundaries to get the single result, but given how many requests we did send (and also would generate while searching for the boundary) it looks to me that 20 cookies to try do counts as solution result. (Tbh, this could be said even about 110 results acquired straight-forwardly.) &lt;/p&gt;

&lt;p&gt;Maybe results are not that clean as instead of "canonical" for the CRIME &lt;code&gt;zlib&lt;/code&gt; here is used &lt;code&gt;miniz_oxide&lt;/code&gt; crate, which should be "close enough"/compatible with &lt;code&gt;zlib&lt;/code&gt; (as indicates provision of the relevant method), but can differ in whatever details. Frankly, I have no side quests here concerned with compression, so if somebody are interested that much in this aspect it will be cute to read your findings on this!&lt;/p&gt;

&lt;p&gt;I'm not sure how &lt;code&gt;ChaCha20Poly1305&lt;/code&gt; play its role in this exercise, AFAIR all write-ups I came across were using something "simpler"/older, and I just wanted to use something "modern"/current. On the other hand the suite already was around and kind of established &lt;a href="https://dev.to/skaunov/tiny-investigation-into-cryptopals-51-2iml"&gt;when the exercise was &lt;br&gt;
released&lt;/a&gt;. It's a more relevant topic to me than compression; though chances that it would be me who'd dig this piece are diminishing. &lt;/p&gt;

&lt;p&gt;Actual question that I still don't find enough motivation to research is why did all my attempts to find that &lt;em&gt;compression (block) border&lt;/em&gt; that is described in references but already having small set of possible solution failed. I feel like translating Python solution, or detailed development of this solution should help, but other things demands this time. So it's a bit, which could be discussed here and returned to once if ever.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rayon&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;chacha20poly1305&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;ChaCha20Poly1305&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;aead&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;KeyInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Aead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AeadCore&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;http_serde&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;http&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HeaderMap&lt;/span&gt;&lt;span class="cm"&gt;/* , version::Http */&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nd"&gt;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;RequestSer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;#[serde(with&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http_serde::method"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// #[serde(with = "http_serde::uri")]&lt;/span&gt;
        &lt;span class="c1"&gt;// uri: Uri,&lt;/span&gt;
        &lt;span class="nd"&gt;#[serde(with&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http_serde::header_map"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HeaderMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// version: Version&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// pub struct Oracle {key: Key&amp;lt;ChaCha20Poly1305&amp;gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// impl Oracle {&lt;/span&gt;
    &lt;span class="c1"&gt;//     pub fn new() -&amp;gt; Oracle {Oracle { key: ChaCha20Poly1305::generate_key(&amp;amp;mut OsRng) }}&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* &amp;amp;self, */&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(request_format(p.clone()));&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req_builded_parts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req_builded_body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
            &lt;span class="nf"&gt;request_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into_parts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(&amp;amp;req_builded_parts);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;req_restiched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RequestSer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req_builded_parts&lt;/span&gt;&lt;span class="py"&gt;.method&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req_builded_parts&lt;/span&gt;&lt;span class="py"&gt;.headers&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;req_builded_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(&amp;amp;req_restiched);&lt;/span&gt;

        &lt;span class="c1"&gt;// let req_serialized: Vec&amp;lt;u8&amp;gt; = req_restiched.serialize(serde_json::Serializer::new(writer));&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;req_serialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;bincode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;req_restiched&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// let compressed = miniz_oxide::deflate::compress_to_vec(&lt;/span&gt;
        &lt;span class="c1"&gt;//     [req_serialized, Vec::from(p)].concat().as_slice(), 0&lt;/span&gt;
        &lt;span class="c1"&gt;// );&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;compressed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;miniz_oxide&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;deflate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;compress_to_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;// let compressed = miniz_oxide::deflate::compress_to_vec_zlib(&lt;/span&gt;
            &lt;span class="n"&gt;req_serialized&lt;/span&gt;&lt;span class="nf"&gt;.as_slice&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(String::from_utf8_lossy(&amp;amp;compressed));&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ChaCha20Poly1305&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;ChaCha20Poly1305&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;generate_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ChaCha20Poly1305&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;generate_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="nf"&gt;.encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compressed&lt;/span&gt;&lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// println!("{ciphertext:?}");&lt;/span&gt;

        &lt;span class="c1"&gt;// println!("{:?}", chrono::offset::Local::now());&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;request_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Host"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hapless.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"Cookie"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sessionid=TmV2ZXIgcmV2ZWFsIHRoZSBXdS1UYW5nIFNlY3JldCE="&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Length"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* holds growing strings of best compressed guesses, should converge to the one 
    that is in the header */&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ( */&lt;/span&gt;&lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="cm"&gt;/* , 0) */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* loop over each symbol of Base64; suppose we know that _secure cookie_ is 
    32 bytes represented in Base64 by looking into our own account in the same system; 
    32 * 8 = 256 div 6 = 42 pad to mod4=0 = 44; 1-based for progress printing */&lt;/span&gt;

    &lt;span class="c1"&gt;// (1..=44).into_par_iter().for_each(|pos| {});&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* holds iterated symbols that passed window check
        with oracle for current position */&lt;/span&gt;
        &lt;span class="c1"&gt;// let mut guesses_new = Vec::new();&lt;/span&gt;

        &lt;span class="cm"&gt;/* it turned out to be awful padding for this challenge
        let padding = (0..(44-pos)).map(|_| "_").collect::&amp;lt;String&amp;gt;();  */&lt;/span&gt;

        &lt;span class="c1"&gt;// proper way would be to use a _base64_ crate&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'0'&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="sc"&gt;'9'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="sc"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="sc"&gt;'z'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'='&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="sc"&gt;'='&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// sorry for dirty hack in the end, ofc there's more graceful way to make an iterator from a `char`&lt;/span&gt;

        &lt;span class="cm"&gt;/* we should try each of the substrings 
        constructed previously with each of new B64 chars */&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;guesses_n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="nf"&gt;.par_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* let mut lengs: Vec&amp;lt;(String, usize)&amp;gt; = */&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.filter_map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="nf"&gt;.is_alphanumeric&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;41&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="cm"&gt;/* _1 */&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sessionid="&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="cm"&gt;/* + padding.as_str() */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="c1"&gt;// let t_2 = String::from(&lt;/span&gt;
                    &lt;span class="c1"&gt;//     /* padding.clone() + */ guess.to_owned() + ch.to_string().as_str() + "sessionid=" /* + padding.as_str() */&lt;/span&gt;
                    &lt;span class="c1"&gt;// );&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t_l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="c1"&gt;// println!("{t_1_l}|{t_2_l}|{guess}|{ch}");&lt;/span&gt;
                    &lt;span class="c1"&gt;// if t_l &amp;lt; t_2_l {Some(guess.to_owned() + &amp;amp;ch.to_string())}&lt;/span&gt;
                    &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;t_l&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="py"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
            &lt;span class="c1"&gt;// let shortest = lengs.iter().map(|x| x.1).min().expect("`lengs` isn't empty");&lt;/span&gt;
            &lt;span class="c1"&gt;// lengs.retain(|x| x.1 == shortest);&lt;/span&gt;
            &lt;span class="c1"&gt;// lengs.into_iter().map(|x| guess.to_owned() + &amp;amp;x.0.to_string()).collect::&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;()&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="nf"&gt;.flatten&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="cm"&gt;/* .filter(|x| !x.is_empty()) */&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;shortest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;guesses_n&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.min&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"`lengs` isn't empty"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// dbg!(&amp;amp;shortest);&lt;/span&gt;
        &lt;span class="n"&gt;guesses_n&lt;/span&gt;&lt;span class="nf"&gt;.retain&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;shortest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;guesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;guesses_n&lt;/span&gt;&lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// for guess in &amp;amp;guesses {&lt;/span&gt;
        &lt;span class="c1"&gt;//     // for ch in ('a'..='z').chain('A'..='Z').chain('0'..='9') {&lt;/span&gt;
        &lt;span class="c1"&gt;//     for ch in '0'..='z' {&lt;/span&gt;
        &lt;span class="c1"&gt;//         // skip non-alphanumerics before padding `pos`itions&lt;/span&gt;
        &lt;span class="c1"&gt;//         if (pos &amp;lt; 41 &amp;amp;&amp;amp; ch.is_alphanumeric()) || pos &amp;gt; 41 {&lt;/span&gt;
        &lt;span class="c1"&gt;//             let t_1 = String::from("sessionid=".to_owned() + guess.as_str() + ch.to_string().as_str() /* + padding.as_str() */);&lt;/span&gt;
        &lt;span class="c1"&gt;//             let t_2 = String::from(&lt;/span&gt;
        &lt;span class="c1"&gt;//                 /* padding.clone() + */ guess.to_owned() + ch.to_string().as_str() + "sessionid=" /* + padding.as_str() */&lt;/span&gt;
        &lt;span class="c1"&gt;//             );&lt;/span&gt;
        &lt;span class="c1"&gt;//             let t_1_l = oracle_the.cast(t_1);&lt;/span&gt;
        &lt;span class="c1"&gt;//             let t_2_l = oracle_the.cast(t_2);&lt;/span&gt;
        &lt;span class="c1"&gt;//             // println!("{t_1_l}|{t_2_l}|{guess}|{ch}");&lt;/span&gt;
        &lt;span class="c1"&gt;//             if t_1_l &amp;lt; t_2_l {guesses_new.push(guess.to_owned() + ch.to_string().as_str());}&lt;/span&gt;
        &lt;span class="c1"&gt;//         }&lt;/span&gt;
        &lt;span class="c1"&gt;//     }&lt;/span&gt;
        &lt;span class="c1"&gt;// }&lt;/span&gt;
        &lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="c1"&gt;// assert!(guesses_new.len() &amp;gt; 0);&lt;/span&gt;
        &lt;span class="c1"&gt;// assert!(guesses_new[0].len() == pos/* , "{l}" */);&lt;/span&gt;

        &lt;span class="c1"&gt;// yank previous guesses set with extended 1 `pos`ition further&lt;/span&gt;
        &lt;span class="c1"&gt;// guesses = guesses_new;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{guesses:?}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"!@#$%^&amp;amp;*()-`~[]}{"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// 0123456789:;&amp;lt;=&amp;gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="nf"&gt;.par_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;padded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;guess_padded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="c1"&gt;// println!("{:?}", &amp;amp;padding[0..i]);&lt;/span&gt;
            &lt;span class="n"&gt;padded&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;guess_padded&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nn"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_padded&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;shortest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;padded&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.min&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;longest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;padded&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.max&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;shortest&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;longest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;padded&lt;/span&gt;&lt;span class="p"&gt;);}&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;shortest&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.min_by_key&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="na"&gt;.1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;dbg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;guesses&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// "abcdefghjjklmnopASBCDEFJIERF1234567890".chars()&lt;/span&gt;

&lt;span class="c1"&gt;// @skeletizzle&lt;/span&gt;
&lt;span class="c1"&gt;// alphanumerics represented as what&lt;/span&gt;

&lt;span class="c1"&gt;// SKaunov — Today at 9:55 PM&lt;/span&gt;
&lt;span class="c1"&gt;// Yep, one symbol, which I append to a String. It could be a char, I guess.&lt;/span&gt;

&lt;span class="c1"&gt;// ari.s — Today at 9:56 PM&lt;/span&gt;
&lt;span class="c1"&gt;// ('A'..'z').into_iter().for_each(|c| println!("{c}"));&lt;/span&gt;
&lt;span class="c1"&gt;// [9:56 PM]&lt;/span&gt;
&lt;span class="c1"&gt;// oops nvm , I didnt think about nums&lt;/span&gt;

&lt;span class="c1"&gt;// skeletizzle — Today at 9:56 PM&lt;/span&gt;
&lt;span class="c1"&gt;// 'a'..='z'.chain('A'..='Z').chain('0'..='9)&lt;/span&gt;

&lt;span class="c1"&gt;// ari.s — Today at 9:58 PM&lt;/span&gt;
&lt;span class="c1"&gt;// Or if you're weird: ('0'..='z').into_iter().filter(|c| c.is_alphanumeric()) (edited)&lt;/span&gt;

&lt;span class="c1"&gt;// https://github.com/wangray/matasano-crypto/blob/master/set7/set7.py#L97&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;padding_chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"!@#$%^&amp;amp;*()-`~[]}{"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;base_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;try_the&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="nf"&gt;.to_owned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;padding_chars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nn"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;try_the&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;base_len&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;try_the&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"we didn't found edge of the block =(("&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>cryptopals</category>
      <category>rust</category>
    </item>
    <item>
      <title>Cryptopals #30: Rust, solution approaches</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Fri, 27 Oct 2023 21:59:18 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-30-rust-solution-approaches-31nj</link>
      <guid>https://forem.com/skaunov/cryptopals-30-rust-solution-approaches-31nj</guid>
      <description>&lt;p&gt;There's few hashing challenges in Cryptopals, and some gave me pretty hard time. This one was solved pretty quickly, I even thought that I could cut too much along the way. Lack of solutions in Rust around got me to ask couple of peers to review the thing. So I received their "ok", and now have a minute to wrap up what I remember and how my approach was different.&lt;/p&gt;

&lt;p&gt;As I wanted to learn more of real-world libs than do petty stuff I was trying to employ real encryption in this challenges as much as I can. This time I was seeking a way to recreate a &lt;code&gt;Digest&lt;/code&gt; core in some intermediate state, but after some time concluded it's barely possible. Even when needed data appropriately structured there's no good way to deal with the system so that it would let me to run methods from the lib. Basically I'm talking about a structure with private fields and methods to construct it which are too sound and correct to help with the challenge. &lt;/p&gt;

&lt;p&gt;So I chose to degrade the lib on purpose by only making respective core fields &lt;code&gt;pub&lt;/code&gt;. I guess I would do it in a more clever way now, but at that time to move forward most straight-forward solution was to hover a whole supplementary repo to GitHub just for a couple of lines &lt;code&gt;patch&lt;/code&gt;. You can find the final &lt;a href="https://github.com/skaunov/challenge-30/blob/master/src/main.rs" rel="noopener noreferrer"&gt;solution there&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope things changed since, but those days I couldn't find a clear Rust solution for this one. Though &lt;a href="https://github.com/bankisan/brykto/blob/main/tests/cryptopals_29_30.rs" rel="noopener noreferrer"&gt;one of my peers added his&lt;/a&gt; own. Which I finally compared and report to you that we both handled the challenge with similar ideas!&lt;/p&gt;

&lt;p&gt;Which one do you like better?&lt;/p&gt;

</description>
      <category>cryptopals</category>
      <category>rust</category>
    </item>
    <item>
      <title>Cryptopals challenge #48 solution</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Sun, 22 Jan 2023 18:22:41 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-challenge-48-solution-5dam</link>
      <guid>https://forem.com/skaunov/cryptopals-challenge-48-solution-5dam</guid>
      <description>&lt;p&gt;I couldn't find a solution in Rust when I wanted, so I decided to cover this.&lt;/p&gt;

&lt;p&gt;This solution received absolutely no optimizations, so there are a lot of space for improvements.&lt;/p&gt;

&lt;p&gt;It dates back to November and initial cleaned version have been lost, so I cleaned it again, now without #47 branch, and maybe forgetting some details, but everything important is there.&lt;/p&gt;

&lt;p&gt;Also this challenge raised couple of question, which landed to &lt;a href="https://crypto.stackexchange.com/questions/102862/bleichenbacher-1998-million-message-attack-cca" rel="noopener noreferrer"&gt;&lt;code&gt;crypto.stackexchange&lt;/code&gt;&lt;/a&gt;. Namely&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why do we get intervals with their ends interchanged? And&lt;/li&gt;
&lt;li&gt;Why does it work to discard intervals in pairs?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have ideas to explain any of those, please put them to the comments or on the linked page.&lt;/p&gt;

&lt;p&gt;If you find links and explanations in the code not clear enough you're always welcome to leave a comment here, or at the Gist page! &lt;a href="https://gist.github.com/skaunov/3c6a5dc68c008bc4865adf720eb589a6#file-main-rs" rel="noopener noreferrer"&gt;https://gist.github.com/skaunov/3c6a5dc68c008bc4865adf720eb589a6#file-main-rs&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>ai</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>tiny investigation into Cryptopals #51</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Fri, 02 Dec 2022 00:47:38 +0000</pubDate>
      <link>https://forem.com/skaunov/tiny-investigation-into-cryptopals-51-2iml</link>
      <guid>https://forem.com/skaunov/tiny-investigation-into-cryptopals-51-2iml</guid>
      <description>&lt;p&gt;I wondered why the challenge page doesn't mention &lt;a href="https://en.wikipedia.org/wiki/CRIME" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/CRIME&lt;/a&gt;, which it totally should if you ask me. X) (I would guess it's just already much more lengthy than other, so they decided to save some scrolling for you.)&lt;/p&gt;

&lt;p&gt;I wanted to see roughly how many time was there between CRIME and challenge-51, and to our disappointment Cryptopals doesn't have any information on release/modification dates on the challenge page. So the best I got is a Reddit comment which gives approximate date of the challenge novelty. It's 2014, Nov; 8 years ago.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reddit.com/r/crypto/comments/2mf0gc/comment/cm7ognr/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l4au1w21i3fx5y8mt7s.png" alt="Cryptopals set 7 Reddit thread" width="530" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Cryptopals #42: personal impressions</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Sun, 13 Nov 2022 08:55:46 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-42-personal-impressions-242a</link>
      <guid>https://forem.com/skaunov/cryptopals-42-personal-impressions-242a</guid>
      <description>&lt;p&gt;Atm I just finished #47, and starting #48. But I need a little break, so I decided get back to this notes and publish them for a bit of relaxation. Spoiler: #47 &lt;strong&gt;and&lt;/strong&gt; #48 are on Mr. Bleichenbacher too. So much of him, a genius man, I guess. But these challenges feel like they worth it, no complains.&lt;/p&gt;

&lt;p&gt;This one is easy to find a good write-up, so let me describe how I &lt;em&gt;didn't solve&lt;/em&gt; it. Actually I'm not unique here, again. (Will add link to a write-up describing the same problem which blocked me.) Though, I completed the code for the solution, and it was a really well math preparation for next challenges.&lt;/p&gt;

&lt;p&gt;So here's a couple of question this challenge left me with, and kind of an answer to one of them, describing what blocked me from solving it.&lt;/p&gt;

&lt;p&gt;The first of my question was: does it really still present? I mean "We find new instances of it every other year or so.", but when does this statement is still relevant? Then I was caught by surprise &lt;em&gt;how much this padding scheme still in use as default&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;So, it's really hard for me to say how wide these &lt;em&gt;intriguing parameters&lt;/em&gt; (&lt;em&gt;exponent = 3&lt;/em&gt;) are in use since the time challenges were introduced. But if we take a little bit more global look (especially from perspective of following challenges of the set), then we will conclude that entire PKCS1* scheme is a problem. And 'oh, boy', how default is this one. It turns out that given the frequency of its misuse (remember that &lt;em&gt;once a couple of years&lt;/em&gt; note?) it were receiving patchy workarounds one by one, making it even more tricky to implement correctly in turn. So the main conclusion seems to be: use other padding schemes! OAEP, PSS, switch to modern cryptography...&lt;/p&gt;

&lt;p&gt;It could be not that bad in this particular challenge, but globally it's very illustrative. And the answer... As soon authors didn't mentioned hash to use with the challenge, I stuck with the most default currently: SHA-256. And the thing is it doesn't leave so much space for &lt;em&gt;garbage&lt;/em&gt; in the end of the payload, so you basically run out of variations to construct a cube for most of the messages. So maybe sha-256 kind of solves the local problem that was present to us. (Obviously at the time of introduction SHA-1 was the go to choice, and its solution isn't constrained so tightly.)&lt;/p&gt;

&lt;p&gt;On the other hand my conclusion(s) should be taken with a bit of salt. I really tried during the challenge to nullify garbage at all (unsuccessfully), then to solve the problem mathematically, and ended up with computational solution. The one thing that was bugging me is that more mathematical checks were telling that there is a solution, but computational were just exhausting the space for it. Maybe it's the one I could revisit later, though I bet the solution indicated by math approach just need some more space for the garbage bytes.&lt;/p&gt;

&lt;p&gt;This one last question would be interesting to discuss with other Cryptopals in anyone would drop a look here! Leave a comment, share your experience.&lt;/p&gt;

</description>
      <category>cryptopals</category>
      <category>rsa</category>
      <category>padding</category>
    </item>
    <item>
      <title>Cryptopals #46: want a write-up?</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Fri, 04 Nov 2022 22:24:45 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-46-want-a-write-up-21p8</link>
      <guid>https://forem.com/skaunov/cryptopals-46-want-a-write-up-21p8</guid>
      <description>&lt;p&gt;I wonder if anybody is interested in &lt;a href="https://cryptopals.com/sets/6/challenges/46" rel="noopener noreferrer"&gt;https://cryptopals.com/sets/6/challenges/46&lt;/a&gt; write-up? I'm finishing it with Nodejs, and it seems like you can easily find code for the challenge, but no actual write-up in English.&lt;/p&gt;

&lt;p&gt;It's mostly about how artificial it is (they warned) so I couldn't find a realistic something in OpenSSL or  to act as victim.&lt;/p&gt;

</description>
      <category>node</category>
      <category>cryptopals</category>
      <category>rsa</category>
    </item>
    <item>
      <title>Cryptopals challenge #38: purpose clarification</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Thu, 03 Nov 2022 00:01:55 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-challenge-38-purpose-clarification-2h0f</link>
      <guid>https://forem.com/skaunov/cryptopals-challenge-38-purpose-clarification-2h0f</guid>
      <description>&lt;p&gt;This text focus not on the solution for the challenge, but on the point of the challenge itself.&lt;/p&gt;

&lt;p&gt;As soon as I completed #38 I checked others solutions, as I didn't feel like I grasped everything this challenge offered. It turned out that I went very close to others path: confusion, modular math, seeking the point of the challenge. And when I was out of things to squeeze out it, tried to find a more reasonable solutions...&lt;/p&gt;

&lt;p&gt;This time without examples, since people could be quite defensive regarding their solutions. But let's get to the questions: what are we really asked to do in this one. &lt;/p&gt;

&lt;p&gt;So in the end of the day I concluded that I mostly miss the point of the challenge.&lt;/p&gt;

&lt;p&gt;I was puzzled why was it proposed to play with &lt;em&gt;b&lt;/em&gt; value, as it's private. And then found a very suitable &lt;a href="http://srp.stanford.edu/ndss.html#SECTION00032300000000000000" rel="noopener noreferrer"&gt;link&lt;/a&gt; which makes things very explicit. (Kudos to &lt;a href="https://github.com/rjpdasilva/cryptopals/blob/d322930cc94cfde28239b9738e8cd36e304532ea/src/cp_test_c38_attacker.py#L23" rel="noopener noreferrer"&gt;the one who left this link in his solution.&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Most of my solution was based on "simplifications" using modular arithmetic. But... It doesn't make sense to play with the parameters, as dictionary attack doesn't rely on it at all. (The confusion that is found in many solutions...)&lt;/p&gt;

&lt;p&gt;After reading the linked section it turns out that it's expected not to &lt;em&gt;simplify&lt;/em&gt; calculations with parameters, but to pass the server validity check (&lt;a href="https://docs.rs/srp/0.6.0/srp/client/struct.SrpClientVerifier.html#method.verify_server" rel="noopener noreferrer"&gt;an example&lt;/a&gt;), without which the dictionary attack would be &lt;strong&gt;plainly impossible,&lt;/strong&gt; since the client would reject guesses!&lt;/p&gt;

&lt;p&gt;My previous solution already traveled this path: for zero-key challenge I was required to comment out &lt;a href="https://docs.rs/srp/0.6.0/src/srp/client.rs.html#193" rel="noopener noreferrer"&gt;safeguards&lt;/a&gt; in the lib. &lt;/p&gt;

&lt;p&gt;So in a more realistic setting most of &lt;em&gt;simplifications&lt;/em&gt; would just lead to kind of "SrpAuthError::IllegalParameter". &lt;/p&gt;

&lt;p&gt;PS&lt;br&gt;
Good passwords are still able to save the day in many cases. From the first of SRP challenges I used a random password, which boiled down this one to brute force, keeping client pretty secure even with MITM.&lt;/p&gt;

</description>
      <category>cryptopals</category>
      <category>srp</category>
    </item>
    <item>
      <title>Cryptopals challenge #33: Implement Diffie-Hellman</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Sun, 16 Oct 2022 23:53:43 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-challenge-33-implement-diffie-hellman-3ma7</link>
      <guid>https://forem.com/skaunov/cryptopals-challenge-33-implement-diffie-hellman-3ma7</guid>
      <description>&lt;p&gt;As usual, after dealing with a challenge, which taught me something, I looked around to see how my solution differs from others. And this time mine turned out to be rather unique.&lt;/p&gt;

&lt;p&gt;No, it's not good (and even not excellent). =) I wanted to see how people solved &lt;code&gt;modexp&lt;/code&gt; part, and I was interested in Rust solutions. All I opened were using &lt;code&gt;modpow&lt;/code&gt; function of &lt;em&gt;bigint&lt;/em&gt; crate.&lt;/p&gt;

&lt;p&gt;After all it said "write your own modexp", and it felt as a useful part of the exercise. So I employed &lt;code&gt;crypto_bigint&lt;/code&gt; crate, and constructed a function for this particular exercise. It's slow and limited to work with 192 bytes integers, but it's still capable to inspire you to tackle this challenge. (Also it should have a problem with exceed bit for big enough numbers, you can take a bigger bigint type if you want to avoid it.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;crypto_bigint&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
    &lt;span class="n"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NonZero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nn"&gt;rand_core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;U3072&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sha3&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Sha3_256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Digest&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_be_hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2u64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a_big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;modexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b_big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;modexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;modexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b_big&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{s}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;hasher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Sha3_256&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.to_be_bytes&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hasher&lt;/span&gt;&lt;span class="nf"&gt;.finalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{result:?}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;modexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;U1536&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;U1536&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;modulus&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ONE&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ZERO&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;modulus_ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* This algorithm is mostly based on Wikipedia
    listing, and the next line is to test the 
    assertion they have. `unwrap`s below turned out 
    to be much more useful during debuggig. */&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus_ch&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nn"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ONE&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
        &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus_ch&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nn"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ONE&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;U3072&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ONE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nn"&gt;NonZero&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;U3072&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_be_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;pad192&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;modulus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;U3072&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_be_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;pad192&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ZERO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nn"&gt;NonZero&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="mi"&gt;2u64&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ONE&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
                    &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nn"&gt;NonZero&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Checked&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
                &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nn"&gt;NonZero&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modulus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="cm"&gt;/* It should be checked that excessive bytes are 
    zero, but today we omit the check. They really 
    should after `% p` */&lt;/span&gt;
    &lt;span class="nn"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_be_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to_be_bytes&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;pad192&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint_192&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;U1536&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.copy_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;uint_192&lt;/span&gt;&lt;span class="nf"&gt;.to_be_bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://rosettacode.org/wiki/Modular_exponentiation#Rust" rel="noopener noreferrer"&gt;&lt;code&gt;fn&lt;/code&gt; at Rosetta&lt;/a&gt; is more ubiquitous, but you still can get the values from there to test this one, created with another crate. Don't forget to make them &lt;code&gt;U1536&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to copy-paste them to employ &lt;code&gt;from_be_hex&lt;/code&gt;, here they are:&lt;br&gt;
a:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006ED80FFACE4DF443C2E9A56155272B9004E01F5DABE5F2181A603DA3EB&lt;br&gt;
b:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005737DF12ECACC95FF94E28463B3CD1DE0C674CB5D079BD3F4C037E48FF&lt;br&gt;
modulus:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001D6329F1C35CA4BFABB9F5610000000000&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cryptopals</category>
    </item>
    <item>
      <title>Cryptopals-25: use `edit` as keystream</title>
      <dc:creator>skaunov</dc:creator>
      <pubDate>Fri, 30 Sep 2022 08:36:04 +0000</pubDate>
      <link>https://forem.com/skaunov/cryptopals-25-use-edit-as-keystream-5h30</link>
      <guid>https://forem.com/skaunov/cryptopals-25-use-edit-as-keystream-5h30</guid>
      <description>&lt;p&gt;Do you want a slightly simpler solution to #25 "Break "random access read/write" AES CTR"? Did you ever wanted to add a crate release (from git) that isn't at &amp;lt;Crates.io&amp;gt;?&lt;/p&gt;

&lt;p&gt;As I mentioned on the &lt;a href="https://dev.to/skaunov/test-3klo"&gt;previous page&lt;/a&gt; I was detailing challenge point and overviewed few solutions. Usually I return back to existing solutions to see the alternatives and check my own solution sanity and correctness. This time was a bit different.&lt;/p&gt;

&lt;p&gt;Surprisingly I didn't found my solution among those I viewed, so let me share it with you. Not to repeat common part in all of them, I just link &lt;a href="https://github.polettix.it/ETOOBUSY/2022/09/10/cryptopals-25/" rel="noopener noreferrer"&gt;a fresh write-up I liked&lt;/a&gt;, and quickly note that instead of getting the key and then deciphering with it, we can just &lt;strong&gt;feed our ciphertext to the &lt;code&gt;edit&lt;/code&gt; function twice&lt;/strong&gt;: as the one we want to edit (basically it will get us right length in most implementations) and the second time as "plaintext" we want to re-encrypt. (Offset should be &lt;em&gt;0&lt;/em&gt;, of course. So the key-stream would be aligned.) This simple trick/tweak will just apply the key-stream against ciphertext and as the result of "&lt;code&gt;edit&lt;/code&gt;" we get plaintext.&lt;/p&gt;

&lt;p&gt;Rust code of the solution: &lt;a href="https://github.com/skaunov/challenge-25" rel="noopener noreferrer"&gt;https://github.com/skaunov/challenge-25&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;I wondered of a clean way to import a particular version of crate from git, as the one I used isn't available from &amp;lt;Crates.io&amp;gt;. And it turned out to be just a few lines to do it neatly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies.ctr]&lt;/span&gt;
&lt;span class="py"&gt;git&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/RustCrypto/block-modes.git"&lt;/span&gt;
&lt;span class="py"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ctr-v0.9.1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>rust</category>
      <category>cryptopals</category>
      <category>tag</category>
    </item>
  </channel>
</rss>
