New to AWS here so please bear that in mind.

I want to encrypt/decrypt data using AWS KMS.

Here is the code I have

const { KMS } = require('@aws-sdk/client-kms');
const { KmsKeyringNode, buildClient } = require('@aws-crypto/client-node');

const kmsAccessKeyId = process.env.KMS_ACCESS_KEY_ID;
const kmsSecretAccessKey = process.env.KMS_SECRET_ACCESS_KEY;
const kmsGeneratorKeyId = process.env.KMS_GENERATOR_KEY_ID;
const kmsKeyId = process.env.KMS_KEY_ID;

const REGIONS = {
  REGION: 'region-here', // Contains AWS region. Value here is just for illustration purposes.
};

const clientProvider = () => new KMS({ region: REGIONS.REGION, credentials: { accessKeyId: kmsAccessKeyId, secretAccessKey: kmsSecretAccessKey } });
const keyring = new KmsKeyringNode({ generatorKeyId: kmsGeneratorKeyId , clientProvider, keyIds: [kmsKeyId ] });
const { encrypt, decrypt } = buildClient();


/**
 * Convert buffer to string.
 */
const convertU8toString = (u8Arr) => {
  const textDecoder = new TextDecoder();

  const str = textDecoder.decode(u8Arr);

  return str;
};

/**
 * Receives a plaintext message typeof string
 * encrypt the string
 * receive back a buffer
 * convert the buffer to base64
 * return the string-version of the base64.
 */
const encryptData = async (value) => {
  try {
    if (!value) throw new Error('No value provided');

    if (typeof value !== 'string') throw new Error('Only value type of string is supported');

    const { result } = await encrypt(keyring, value);
    const storableMessage = result.toString('base64');

    return storableMessage;
  } catch (err) {
    throw err;
  }
};

/**
 * Receives a base64 encoded message typeof string
 * convert the base64 back to a buffer.
 * decrypt the buffer
 * receive back a buffer
 * return the plaintext message typeof string.
 */
const decryptData = async (value) => {
  try {
    if (!value) throw new Error('No value provided');

    if (typeof value !== 'string') throw new Error('Only value type of string is supported');

    const newBuff = Buffer.from(value, 'base64');
    const { plaintext } = await decrypt(keyring, newBuff);

    return convertU8toString(plaintext);
  } catch (err) {
    throw err; // Our own custom error. Just re-throw.
  }
};

So the code above seemed to work.
I was able to encrypt and decrypt data no problem.

The problem arises when you use encrypt and decrypt consicutively in a set period of time.
The error:

Error: connect EHOSTUNREACH 52.94.177.94:443
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1494:16) {
  errno: -113,
  code: 'EHOSTUNREACH',
  syscall: 'connect',
  address: '52.94.177.94',
  port: 443,
  '$metadata': { attempts: 1, totalRetryDelay: 0 }
}

randomly occurs. You have to wait for a couple of time to use encrypt and decrypt data again before it will work again properly.

This issue is very evident when running automated tests.

Even if I run only 1 test test.only sometimes the error randomly pops up. Sometimes it doesn’t.

It is very confusing.

It looks like encrypt and decrypt connects to AWS everytime it is run because the ip seemed to belong from AWS (ipinfo:52.94.177.94) and for a random reason it fails and throws that error.

Any help to resolve the issue or point out where or what I am doing wrong is highly appreciated.

Thanks in advance.