<?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: Jeff Gould</title>
    <description>The latest articles on Forem by Jeff Gould (@jrgould).</description>
    <link>https://forem.com/jrgould</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%2F14982%2Fefeb9719-6324-4771-ab1b-309409c9542e.jpg</url>
      <title>Forem: Jeff Gould</title>
      <link>https://forem.com/jrgould</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jrgould"/>
    <language>en</language>
    <item>
      <title>Reimplementing grep in JavaScript using rolling hashes</title>
      <dc:creator>Jeff Gould</dc:creator>
      <pubDate>Fri, 03 Jan 2020 14:22:45 +0000</pubDate>
      <link>https://forem.com/jrgould/how-to-write-a-rolling-hash-string-search-algorithm-in-javascript-41cc</link>
      <guid>https://forem.com/jrgould/how-to-write-a-rolling-hash-string-search-algorithm-in-javascript-41cc</guid>
      <description>&lt;p&gt;Some time ago I watched an interview on &lt;a href="//interviewing.io"&gt;interviewing.io&lt;/a&gt; where the task that the interviewer posed to the interviewee was to create a function called &lt;code&gt;grep()&lt;/code&gt; that should accept two strings, &lt;code&gt;haystack&lt;/code&gt; and &lt;code&gt;needle&lt;/code&gt;, and return an array of indexes where &lt;code&gt;needle&lt;/code&gt; exists in &lt;code&gt;haystack&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive approach
&lt;/h2&gt;

&lt;p&gt;The naive approach is pretty simple in javascript, just loop through each letter in the &lt;code&gt;haystack&lt;/code&gt;, grab a slice starting at the current letter that is the length of the needle, and check to see if that slice is equal to the needle.&lt;/p&gt;

&lt;p&gt;Here's what that might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Naive approach&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;grepNaive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;substr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;substr&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;matches&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;



&lt;p&gt;This works great but it's not super efficient. The loop only runs once for each possible match, but the string comparison is arguably a &lt;em&gt;heavy&lt;/em&gt; operation that further requires that each letter in the slice be compared to each letter in the &lt;code&gt;needle&lt;/code&gt;. JavaScript hides this bit of complexity from us by allowing us to check string equality, but under the hood each individual letter still needs to  be evaluated and since we're making this comparison once for each letter in the &lt;code&gt;haystack&lt;/code&gt;, most letters actually get compared multiple times. &lt;/p&gt;

&lt;h2&gt;
  
  
  A more efficient solution: rolling-hash search
&lt;/h2&gt;

&lt;p&gt;If you were to get asked this question in an interview, this is the point where the interviewer would say something a long the lines of "this is great, but is there a more efficient solution?" Any maybe you've memorized &lt;a href="https://www.geeksforgeeks.org/rabin-karp-algorithm-for-pattern-searching/"&gt;Rabin-Karp&lt;/a&gt; because you're a 10x-rockstar-ninja-guru. Awesome. If you're like me and you have no idea what fish have to do with pattern matching algorithms - then you've come to the right place!&lt;/p&gt;

&lt;p&gt;First thing's first: What even is a rolling hash? Well, basically it's the idea that you can find hash of a substring within a string and then shift the first letter out of that hash and push another letter onto the end of the hash to find the hash of the substring next to the original without recalculating the entire hash. To do that we need to come up with a way to hash strings that will allow us to do this shift and push operation while still producing hashes that don't produce too many collisions (eg &lt;code&gt;hash('ba') ≠ hash('ab')&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;To do that, let's start simple and hash just a single character with a &lt;code&gt;hash1()&lt;/code&gt; function. We can do this by finding the character code of a character and just multiplying that by a large number - multiplying by a large number will help us to avoid hash collisions when we're finding hashes of whole strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hash1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charCodeAt&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="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;256&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;



&lt;p&gt;We could use this function to create hashes of stings by adding the hashes together, but right now this will still be very prone to collision because &lt;code&gt;hash1('a') + hash1('b') === hash1('b') + hash1('a')&lt;/code&gt; - we need to add a way to create hashes that respect the order of the characters in a string, and we can do that by first adding a &lt;code&gt;vector&lt;/code&gt; argument to our &lt;code&gt;hash1()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hash1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vector&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charCodeAt&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="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;vector&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;



&lt;p&gt;All that's changed here is that we're accepting that &lt;code&gt;vector&lt;/code&gt; argument and using it as an exponent on our hash - so now, since &lt;code&gt;vector&lt;/code&gt; defaults to &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;hash1('d')&lt;/code&gt; will actually return the same value as &lt;code&gt;'d'.charCodeAt(0)&lt;/code&gt;  which is &lt;code&gt;100&lt;/code&gt; but we can specify a vector to signify different positions of the letter, so the &lt;code&gt;hash1&lt;/code&gt; of the letter &lt;code&gt;d&lt;/code&gt; within the string &lt;code&gt;mad&lt;/code&gt; would be &lt;code&gt;hash1('d', 2)&lt;/code&gt; which would be &lt;code&gt;6553600&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we just need to create a string hashing function that will use our &lt;code&gt;hash1()&lt;/code&gt; function to create hashes of whole strings. We can do that by just passing each letter to &lt;code&gt;hash1()&lt;/code&gt;, using its position in the string as the &lt;code&gt;vector&lt;/code&gt; and adding all of those values up. I'll do that by splitting the string up into an array of characters and then utilize JavaScript's &lt;code&gt;Array.map&lt;/code&gt; and &lt;code&gt;Array.reduce&lt;/code&gt; methods to find the hash value and then get the sum of all hash values in the string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// transform the string into an array of characters&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// hash each character, using its index in the array as vector&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;add&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="c1"&gt;// add all of the values up (assume add function defined as `(a,b) =&amp;gt; a+b`)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What's nice about this hash method is that while there is a low chance of hash collisions, the math is pretty straightforward which allows us to modify the hash without having to jump through too many hoops. For example, if you find the hash for a string like &lt;code&gt;foo&lt;/code&gt; (&lt;code&gt;7303014&lt;/code&gt;) and want to find the hash for just &lt;code&gt;oo&lt;/code&gt;, all you have to do is subtract the hash for &lt;code&gt;f&lt;/code&gt; which is just its character code &lt;code&gt;7303014 - 102 = 7302912&lt;/code&gt; and then shift the exponents on the rest of the hashed characters down by one which can be done by dividing the the remaining hash number by 256 &lt;code&gt;7302912/256 = 28527&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why divide by 256? Because &lt;code&gt;(a*256^n)/256&lt;/code&gt; is equal to &lt;code&gt;(a*256^(n-1))&lt;/code&gt;. So assuming the character code for "f" is 102 and "o" is 111, we can find the original hash using the following equation &lt;code&gt;hash(foo) = (102*256^0) + (111*256^1) + (111*256^2)&lt;/code&gt; so when we subtract &lt;code&gt;102&lt;/code&gt; that equation looks like &lt;code&gt;hash(_oo) = (111*256^1) + (111*256^2)&lt;/code&gt; and then dividing by 256 gets us &lt;code&gt;hash(oo) = (111*256^0)+(111*256^1)&lt;/code&gt;. Let's create a function to express that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;shiftHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firstChar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalHash&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;hash1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstChar&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;256&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;



&lt;p&gt;Next, we can create a function to pop a character on to the end of the existing hash. To add a character onto an existing hash, we just need to add the &lt;code&gt;hash1()&lt;/code&gt; of the character that we'd like to add, with the vector appropriate for the position that we'll add it. So if we have the hash for &lt;code&gt;oo&lt;/code&gt; (&lt;code&gt;28527&lt;/code&gt;) and we'd like to find the hash for &lt;code&gt;oof&lt;/code&gt;, we just need to find &lt;code&gt;hash1('f', 2) //6684672&lt;/code&gt; and add that to the existing hash &lt;code&gt;28527 + 6684672 = 6713199&lt;/code&gt;. Here's how that would work as a function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;pushHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;strLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextChar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;originalHash&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;hash1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextChar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;strLen&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;// Subtract 1 from strLen because indexes start at 0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And from that we can compose a &lt;code&gt;rollHash&lt;/code&gt; function that will remove the first character from an existing hash and add a new character onto the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;rollHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firstChar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextChar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;strLen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shiftedHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shiftHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firstChar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pushHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shiftedHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;strLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextChar&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;



&lt;p&gt;Now we can find the hash of a string &lt;code&gt;hash('foo') //7303014&lt;/code&gt; and then easily find the hash of &lt;code&gt;oof&lt;/code&gt; by using &lt;code&gt;rollHash(7303014, 'f', 'f', 3); //6713199&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To put it all together, we can now build our &lt;code&gt;grep&lt;/code&gt; function by looping through our &lt;code&gt;haystack&lt;/code&gt; to find occurrences of our &lt;code&gt;needle&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Rolling Hash Approach&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;grepHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// This will store all indexes where a match occurs&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;needleHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;needleLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currentHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substr&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="nx"&gt;needleLength&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needleLength&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="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needleHash&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;currentHash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// If hashes match, push the current index into matches&lt;/span&gt;
    &lt;span class="nx"&gt;currentHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rollHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;currentHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// first character in current search&lt;/span&gt;
      &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;needleLength&lt;/span&gt;&lt;span class="p"&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;// next letter in haystack&lt;/span&gt;
      &lt;span class="nx"&gt;needleLength&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;matches&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;



&lt;p&gt;The code here is definitely more complicated, but this is often the case with optimized solutions - we're doing more work up front to prevent the computer from having to do it at runtime. Here it is in a &lt;a href="https://codesandbox.io/s/funny-driscoll-huj8d?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark"&gt;CodeSandbox&lt;/a&gt; for you to play around with.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/funny-driscoll-huj8d"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;To be completely honest, modern hardware and languages would probably still support the naive solution just fine, even at scale. So this may only be something that you use in the context of interviewing or if you enjoy trying to level up on platforms like HackerRank. As a self-taught developer, I've come to enjoy learning about algorithms because even if I don't end up using them in my day to day, it helps me to expand the way that I think about code and problem solving.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>algorithms</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>5 Great Git CLI Shortcuts </title>
      <dc:creator>Jeff Gould</dc:creator>
      <pubDate>Thu, 26 Sep 2019 18:55:53 +0000</pubDate>
      <link>https://forem.com/jrgould/5-great-git-cli-shortcuts-2leg</link>
      <guid>https://forem.com/jrgould/5-great-git-cli-shortcuts-2leg</guid>
      <description>&lt;p&gt;I think we're all onboard with git these days - it's the best way to collaborate on code with a team or to just keep things organized, synchronized, and tidy when you're working alone. But there's still a great divide amongst git users - those who are Git CLI purists, and those of us who are happy to fire up the likes of Tower, SourceTree, Github Desktop, or one of the (probably) hundreds of other options. &lt;/p&gt;

&lt;p&gt;CLI users will argue that it's faster and easier to use Git on the CLI but GUI users like myself are usually thinking, "I don't have that much room in my brain, I like buttons..." And, honestly, I think both are right. I've recently been working on my Git CLI skills and a great way to get better at using Git on the CLI is to create aliases for things you do often, especially when they require complex git commands - so here are a few of my favorite git aliases, straight from my &lt;code&gt;.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;gro&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gro&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git reset --hard @{u}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In my mind, &lt;code&gt;gro&lt;/code&gt; is short for "git reset origin" but I think the whole &lt;code&gt;#{u}&lt;/code&gt; thing means &lt;code&gt;upstream tracking branch&lt;/code&gt; or something like that. I'll use this when I just want to make sure that I'm working with exactly the same version of this branch that's on github. Now, you can use &lt;code&gt;git pull&lt;/code&gt; which will merge remote changes into your local branch or just fast-forward the branch if it can - but I like &lt;code&gt;gro&lt;/code&gt; because it will just blow away any edits or even commits that I've made in my current working tree which is often useful if I've been doing some experimenting but now I'm ready to get down to business.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;gpub&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gpub&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git push --set-upstream origin &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git_current_branch&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Whenever I'm working on a new branch and am ready to push it up to github I'll just run &lt;code&gt;gpub&lt;/code&gt; (shorthand for "git publish") which handles the minutia of telling my origin repo what I want the branch to be called (obviously, I just want it to be the same) and setting up the tracking so that I can just &lt;code&gt;git push&lt;/code&gt; my changes in the future. If you try to &lt;code&gt;git push&lt;/code&gt; when you don't have a tracking branch, git will give you an error that guides you in the right direction, but &lt;code&gt;gpub&lt;/code&gt; is just so much easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;gst&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git status -sb"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gsb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gst"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gst"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is an easy one, &lt;code&gt;gst&lt;/code&gt; is just a better &lt;code&gt;git status&lt;/code&gt; because it throws on the &lt;code&gt;-s&lt;/code&gt; option which generates less verbose output (easier to read) and the &lt;code&gt;-b&lt;/code&gt; option which shows the current branch and tracking branch at the top (eg &lt;code&gt;## dev...origin/dev&lt;/code&gt;). I also have a few aliases for the original alias because sometimes I forget. &lt;/p&gt;

&lt;p&gt;"Why not use &lt;code&gt;gs&lt;/code&gt; as the alias for that, it's so much easier!" Is what you're probably asking yourself. Well, that's because...&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;gs&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git stash"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Another super simple one but I do a fair amount of stashing and stash popping. Bonus tip is that you can still add arguments and subcommands to the end of an alias so you'll often catch me running &lt;code&gt;gs push -m "WIP: converting React to Angular"&lt;/code&gt; or just &lt;code&gt;gs pop&lt;/code&gt;, &lt;code&gt;gs list&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Honestly, I could probably swap the aliases for &lt;code&gt;gs&lt;/code&gt; and &lt;code&gt;gst&lt;/code&gt; since I'm sure I use &lt;code&gt;git status&lt;/code&gt; more than I use &lt;code&gt;git stash&lt;/code&gt; but the hard part would be getting my fingers to update their keymaps.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;gcr&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;gcr&lt;span class="o"&gt;(){&lt;/span&gt; git checkout &lt;span class="nt"&gt;-t&lt;/span&gt; origin/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Okay, not an alias, but a function that basically works like an alias. Short for "git checkout remote", this will let you check out a remote branch locally and set the tracking up for you as well. I often use this after I've copied the branch name from a PR on github so I can run &lt;code&gt;gcr branch-to-review&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I'm particularly lazy, so there's also a bonus alias here for mac users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gcrc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gcr &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pbpaste&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the same as &lt;code&gt;gcr&lt;/code&gt; but it will just use the contents of your clipboard for the branch name. &lt;/p&gt;

&lt;h3&gt;
  
  
  Git Commit
&lt;/h3&gt;

&lt;p&gt;I've got quite a few more git aliases, but those are pretty standard fare and half of the time I forget to use aliases like &lt;code&gt;gp&lt;/code&gt; instead of &lt;code&gt;git pull&lt;/code&gt; when the git commands are more obvious to me. I think the great part of having aliases set up for the more complex or esoteric git commands that you use is that you don't have to memorize the command right away in order to be able to use it, just remember the alias and you can also use &lt;code&gt;which&lt;/code&gt; to remind yourself what it actually does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;which gro
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;gro: aliased to git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; @&lt;span class="o"&gt;{&lt;/span&gt;u&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's super helpful. Another trick I use is to actually group all of my git aliases in a .gitaliases file and import them into my &lt;code&gt;.zshrc&lt;/code&gt; file - then I can also set up an alias to list out all of my git aliases, kind of like a cheat sheet!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# somewhere in .zshrc&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.gitaliases &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; 
  &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.gitaliases
  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gcheat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\c&lt;/span&gt;&lt;span class="s2"&gt;at &lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.gitaliases"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Git Merge
&lt;/h3&gt;

&lt;p&gt;Do you have any git aliases or even non-git cli aliases, or functions that you couldn't live with out? Let me know!&lt;/p&gt;

</description>
      <category>git</category>
      <category>webdev</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Use the Web Crypto API to Generate a Public / Private Key Pair for End to End, Asymmetric Cryptography on the Web</title>
      <dc:creator>Jeff Gould</dc:creator>
      <pubDate>Thu, 26 Sep 2019 04:01:36 +0000</pubDate>
      <link>https://forem.com/jrgould/use-the-web-crypto-api-to-generate-a-public-private-key-pair-for-end-to-end-asymmetric-cryptography-on-the-web-2mpe</link>
      <guid>https://forem.com/jrgould/use-the-web-crypto-api-to-generate-a-public-private-key-pair-for-end-to-end-asymmetric-cryptography-on-the-web-2mpe</guid>
      <description>&lt;p&gt;I'll preface this by saying that I'm not cryptography expert - just a dev who has found himself interested in the topic of cryptography in general and in asymmetric cryptography more specifically. These concepts are incredibly deep and I will barely scratch the surface but let's dip our toes in, shall we?&lt;/p&gt;

&lt;h2&gt;
  
  
  Public Key What Now?
&lt;/h2&gt;

&lt;p&gt;Public key cryptography (or asymmetric cryptography if you nasty), is a concept in cryptography that piqued my interest about a year ago because at first glance it doesn't make any sense but seems incredibly useful. It's the idea that you can create a set of cryptographic keys that are designed to work in tandem where one key can encrypt data that can then only be decrypted by the other key. &lt;/p&gt;

&lt;p&gt;This may sound confusing but it's the crux of quite a bit of the encryption that we use on a daily basis (ssh, ssl, other acronyms starting with &lt;code&gt;s&lt;/code&gt;) and for good reason: We need to be able to share secrets in an untrusted environment. &lt;/p&gt;

&lt;p&gt;I want to get to the code, so if you need more explanation on public key cryptography, I'd recommend watching this &lt;a href="https://www.youtube.com/watch?v=GSIDS_lvRv4"&gt;great video from Computerphile&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter &lt;code&gt;window.crypto.subtle&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we've got the &lt;em&gt;what&lt;/em&gt; out of the way, let's get to the &lt;em&gt;how&lt;/em&gt; which involves using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API"&gt;Web Crypto API&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Generating the keypair is actually super simple using &lt;code&gt;crypto.subtle.generateKey&lt;/code&gt; - the hard part is knowing what settings to use. I'd like to use RSA-OAEP with the recommended modulusLength of &lt;code&gt;4096&lt;/code&gt; and recommended publicExponent of &lt;code&gt;65437&lt;/code&gt; (which needs to be expressed as a UInt8Array) and we'll use the &lt;code&gt;SHA-256&lt;/code&gt; algorithm hashing algorithm. &lt;/p&gt;

&lt;p&gt;Now that we've got those variables figured out, we just need to plug them in to the &lt;code&gt;generateKey&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keyPair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RSA-OAEP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;modulusLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;publicExponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&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;1&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SHA-256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encrypt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decrypt&lt;/span&gt;&lt;span class="dl"&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;



&lt;p&gt;The above code will return a promise that will resolve with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CryptoKeyPair"&gt;&lt;code&gt;CryptoKeyPair&lt;/code&gt;&lt;/a&gt; object that looks like &lt;code&gt;{publicKey: CryptoKey, privateKey: CryptoKey&lt;/code&gt;. Easy peasy. &lt;/p&gt;

&lt;h2&gt;
  
  
  What now?
&lt;/h2&gt;

&lt;p&gt;That's really it, but also it's kind of useless. First of all, the &lt;code&gt;CryptoKey&lt;/code&gt;s contained within the &lt;code&gt;CryptoKeyPair&lt;/code&gt; object will kind of only work on the current page that you're on. So, if you ask me, they're basically only good for demonstration purposes in their current state. &lt;/p&gt;

&lt;p&gt;The next thing that we need is to be able to export them so that they're re-usable and for my money, the most convenient way to do that is to export them as JSON Web Keys since the Web Crypto API supports that out of the box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exportKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jwk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exportKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jwk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that we have exported our keypair as JWKs, we can keep our private key somewhere safe and–for example–publish our public key to allow encrypted messages that only we can decrypt to be sent to us via untrusted means. But we'll save that for another day. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cryptography</category>
      <category>crypto</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
