How to build a Password Manager with Node.js

How to build a Password Manager with Node.js

Lets start by understanding the basic concepts and build the backend for the application using MongoDB, Crypto, GraphQL and Apollo Server

ยท

4 min read

A password manager is a computer program that allows users to store, generate, and manage their passwords for local applications and online services. A password manager assists in generating and retrieving complex passwords, storing such passwords in an encrypted database, or calculating them on demand. For the past seven years "123456" and "password" have been the two most commonly used passwords on the web. The problem is, most of us don't know what makes a good password and aren't able to remember hundreds of them anyway.

Why Not Use Your Browser?

Most web browsers offer at least a rudimentary password manager. (This is where your passwords are stored when Google Chrome or Mozilla Firefox ask if you'd like to save a password.) This is better than reusing the same password everywhere, but browser-based password managers are limited. Read More

package.json

"dependencies": {
  "apollo-server": "^3.1.2",
  "dotenv": "^10.0.0",
  "graphql": "^15.5.1",
  "mongoose": "^6.0.7"
},

crypto package is now a built-in Node module.

Encryption

We are going to use the AES algorithm which is an iterative, symmetric-key block cipher that supports cryptographic keys (secret keys) of 128, 192, and 256 bits to encrypt and decrypt data in blocks of 128 bits. The below figure shows the high-level AES algorithm:

JavaScript-AES-256-GCM-Encryption-and-Decryption-Example.png

Note : ENCRYPT_KEY must be of 32 bytes

const encrypt = (password) => {
  const iv = Buffer.from(randomBytes(16));
  // iv : initialization vector
  const cipher = createCipheriv(
    "aes-256-gcm",
    Buffer.from(process.env.ENCRYPT_KEY),
    iv
  );
  const encpass = Buffer.concat([cipher.update(password), cipher.final()]);
  return {
    iv: iv.toString("hex"),
    password: encpass.toString("hex"),
    tag: cipher.getAuthTag().toString('hex')
  };
};

Know more about createCipheriv function and Buffer.

What is IV?

In cryptography, an initialization vector (IV) or starting variable (SV) is an input to a cryptographic primitive being used to provide the initial state.

What is 'aes-256-gcm' ?

In cryptography, Galois/Counter Mode (GCM) is a mode of operation for symmetric-key cryptographic block ciphers which is widely adopted for its performance. GCM throughput rates for state-of-the-art, high-speed communication channels can be achieved with inexpensive hardware resources. The operation is an authenticated encryption algorithm designed to provide both data authenticity (integrity) and confidentiality. GCM is defined for block ciphers with a block size of 128 bits. Galois Message Authentication Code (GMAC) is an authentication-only variant of the GCM which can form an incremental message authentication code. Both GCM and GMAC can accept initialization vectors of arbitrary length.

What is tag ?

The authentication tag is defined as an output parameter in GCM. In all the API's I've encountered it's appended to the ciphertext. Where it is actually placed is up to the protocol designer. The name "tag" of course kind of indicates that it should be tagged to the ciphertext and that may well mean direct concatenation. For the sake of clarity, we have placed it as a separate key.

Decryption

const decrypt = (encpass) => {
  const decipher = createDecipheriv(
    "aes-256-gcm",
    Buffer.from(process.env.ENCRYPT_KEY),
    Buffer.from(encpass.iv, "hex")
  );
  decipher.setAuthTag(Buffer.from(encpass.tag, 'hex'));
  const decpass = Buffer.concat([
    decipher.update(Buffer.from(encpass.password, "hex")),
    decipher.final(),
  ]);
  return decpass.toString();
};

Know more about createDecipheriv function

Moment of truth

image.png

Success ๐Ÿฅณ

The function is able to retrieve the original plain text password from the encrypted data, that means encryption and decryption are both working properly.

Why apollo-server ?

Apollo Server is a community-maintained open-source GraphQL server. It works with many Node.js HTTP server frameworks, or can run on its own with a built-in Express server. Read More

Setup apollo-server

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => ({ req }),
});

connect(process.env.MONGODB, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
  .then(() => {
    console.log(`Database Connected ๐Ÿ”ฅ`);
    return server.listen({ port: process.env.PORT });
  })
  .then(({ url }) => {
    console.log(`${url} : Server Running ๐Ÿ”ฅ`);
  });

Know more about GraphQL Schemas, TypeDefs & Resolvers

image.png

Now we can use any API client to quickly and easily send GraphQL requests at port 5555. In the next part, we'll create a front-end for the same with proper user-authentication, login/signup mutations, create/retrive password query and a decent looking UI for the password manager.

This is all for this article. Hope you found it helpful :)

You can find me on Twitter where I'm also sharing my journey as a FullStack Developer.

ย