<?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: shahinghasemi</title>
    <description>The latest articles on DEV Community by shahinghasemi (@shahinghasemi).</description>
    <link>https://dev.to/shahinghasemi</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%2F522832%2F9895ad6f-70df-40c2-91ed-85741c8da7f0.JPG</url>
      <title>DEV Community: shahinghasemi</title>
      <link>https://dev.to/shahinghasemi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shahinghasemi"/>
    <language>en</language>
    <item>
      <title>Fullstack AES-GCM encryption-decryption in node.js and the client-side</title>
      <dc:creator>shahinghasemi</dc:creator>
      <pubDate>Fri, 12 Feb 2021 15:26:33 +0000</pubDate>
      <link>https://dev.to/shahinghasemi/fullstack-aes-gcm-encryption-decryption-in-node-js-and-the-client-side-8bm</link>
      <guid>https://dev.to/shahinghasemi/fullstack-aes-gcm-encryption-decryption-in-node-js-and-the-client-side-8bm</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
You can find the fully workable gist code &lt;a href="https://gist.github.com/shahinghasemi/8008ba4918feeed08b14f7b9b3a32610"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;AES(Advanced Encryption Standard) is a symmetric kind of cryptographic method which has different modes that you can read further here.&lt;br&gt;
Without any further let’s get to the point. I wanted to encrypt some messages on the server side (Node.js) and send that encrypted message back to the client-side which can be pretty anything, e.g. React, Vue, Angular, vanilla JS, etc.&lt;br&gt;
Since cryptographic stuff is sensitive, I wanted to do so using Native APIs that browser offers out of the box but I occurred some weird problems due to lack of enough resources for AES-GCM method, but finally I go the solution.&lt;br&gt;
This is the code that should be run on the server side (node.js)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function encrypt(message){
  const KEY = crypto.randomBytes(32)
  const IV = crypto.randomBytes(16)
  const ALGORITHM = 'aes-256-gcm';

  const cipher = crypto.createCipheriv(ALGORITHM, KEY, IV);
  let encrypted = cipher.update(message, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  const tag = cipher.getAuthTag()

  let output = {
    encrypted,
    KEY: KEY.toString('hex'),
    IV: IV.toString('hex'),
    TAG: tag.toString('hex'),
  }
  return output;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is the code that should be run on the client side (browser)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function decrypt() {
  let KEY = hexStringToArrayBuffer(data.KEY);
  let IV = hexStringToArrayBuffer(data.IV);
  let encrypted = hexStringToArrayBuffer(data.encrypted + data.TAG);

  window.crypto.subtle.importKey('raw', KEY, 'AES-GCM', true, ['decrypt']).then((importedKey)=&amp;gt;{
    console.log('importedKey: ', importedKey);
    window.crypto.subtle.decrypt(
      {
        name: "AES-GCM",
        iv: IV,
      },
      importedKey,
      encrypted
    ).then((decodedBuffer)=&amp;gt;{
      let plaintext = new TextDecoder('utf8').decode(decodedBuffer);
      console.log('plainText: ', plaintext);
    })
 })

function hexStringToArrayBuffer(hexString) {
  hexString = hexString.replace(/^0x/, '');
  if (hexString.length % 2 != 0) {
    console.log('WARNING: expecting an even number of characters in the hexString');
  }
  var bad = hexString.match(/[G-Z\s]/i);
  if (bad) {
      console.log('WARNING: found non-hex characters', bad);    
  }
  var pairs = hexString.match(/[\dA-F]{2}/gi);
  var integers = pairs.map(function(s) {
      return parseInt(s, 16);
  });
  var array = new Uint8Array(integers);
  return array.buffer;
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think the code is expressive enough but the take away is  &lt;strong&gt;we should concatenate the encrypted and authentication tag together and passed it to the decrypt method of the subtle crypto API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you've got any question, let me know on the comments ;)&lt;/p&gt;

</description>
      <category>node</category>
      <category>encryption</category>
      <category>crypto</category>
    </item>
  </channel>
</rss>
