DEV Community

Cover image for How to build a Password Manager with Node.js : Part - 1
Rohan
Rohan

Posted on

How to build a Password Manager with Node.js : Part - 1

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"
},
Enter fullscreen mode Exit fullscreen mode

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"),
  };
};
Enter fullscreen mode Exit fullscreen mode

Know more about createCipheriv function and Buffer Class.

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();
};
Enter fullscreen mode Exit fullscreen mode

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 🔥`);
  });
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (0)