node.jssecurityencryption-asymmetric

Is it safe to load security keys in memory or should I read from file every time?


I have a node.js server that uses a pair of asymmetric keys for enc/decryption. About 90% of the functionality of the server relies on actively encrypting and decrypting data, or verifying JWT tokens signed with these keys.

For security reasons, it is always recommended to dispose, after usage, of any plain-text strings or Buffers where such keys are loaded in memory. However, given the massive usage of the keys, reading them from file every time becomes a huge performance bottleneck.
For DRY (Don't Repeat Yourself) reasons, it also makes you question why each function has to read the key files themselves every time.

My question is: how safe is it to load these keys in memory instead of reading them each time from file?
Would you be able to recommend any different approach? See code below:

export and import from file

import * as fs from "node:fs";

export const PRIVATE = fs.readSync("./private.key");
export const PUBLIC = fs.readSync("./public.key");

// in another file
import * as KEYS from "./keys";

function doSomething(data) {
  return JWT.sign(data, KEYS.PUBLIC);
}

VS

in-place read from file

import * as fs from "node:fs";


function doSomething(data) {
  const PUBLIC_KEY = fs.readSync("./public.key");
  return JWT.sign(data, PUBLIC_KEY);
}


Solution

  • First of all, you want to know whether it is secure, not whether it is safe. Safe means, that the act of reading the data does not hurt the app. It does not.

    Is it secure, to read the data every time from the file then? Secure in its broad term means that some data is made available by the system in a way that ensures integrity and confidentiality. So you have the notion of availability on one side, and integrity and confidentiality on the other.

    We already know that reading secrets every time disrupts availability. Does it improve integrity and confidentiality so much that it is worth it? Well, you can say for sure that integrity stays the same - no data changes there.

    So the only question is about confidentiality. Do we gain something that is worth it? Here comes a bit of threat modeling into play. What are you afraid of when you do not want to keep secrets in memory? That someone does a memory dump and extracts the secrets from memory on your server? That someones executes code remotely on your server and gets access to the secrets?

    You need to have admin level privileges already to do a memory dump. And if someone can execute malicious code in your application then having some secrets only temporary will not save you much.

    Based on the logic here I would simply hold the secrets in memory. I would also update the threat analysis if I get insight into new threats that appear in the future.