npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

encrypt-storage

v2.13.3

Published

Wrapper for encrypted localStorage and sessionStorage in browser

Downloads

43,374

Readme

stargazers count maintenance npm sponsors package size Code Size Version Build Status Coverage Status License Node CI CodeQL npm published jsdelivery

OBS: This is the new version of Encrypt Storage, it has breaking changes that will not be described below. For version 1.3.X documentation, access this link.

The Encrypt Storage is a wrapper for native Storage of browser.

Using the crypto-js library as an encryption engine, it saves the encrypted data on the selected storage in the same way as the native Storage.

HELP THIS PROJECT: Your Github star can help this project. Leave a star, it costs nothing.

⚠️ IMPORTANT: Nothing on the front end is entirely secure. The library's proposal is to make it difficult for the user to see the data through the console, but as the secret key is on the front end, if the user searches hard enough, he will end up finding it. Just to make it clear that nothing is completely secure on the front end. Thank you for your attention.

Features

  • Save encrypted data in localStorage and sessionStorage
  • Recover encrypted data with get functions
  • Use in the same way as native Web Storage (localStorage and sessionStorage)
  • If you use the stateManagementUse option, the data acquired in get functions will not have their return transformed into Javascript objects.
  • Use with stateManagement persisters (vuex-persist and redux-persist*)

Installing

To run this project in the development mode, you'll need to have a basic environment with NodeJs and Yarn installed.

Using npm:

$ npm install encrypt-storage

Or yarn:

$ yarn add encrypt-storage

Using CDNs:

Unpkg:

<body>
  <!-- ...after other codes -->
  <script src="https://unpkg.com/encrypt-storage@latest/dist/index.js"></script>
  <script>
    const encryptStorage = new EncryptStorage('secret-key-value');
  </script>
</body>

OBS: Unpkg doesn't have a counter badge

JS Delivery:

<body>
  <!-- ...after other codes -->
  <script src="https://cdn.jsdelivr.net/npm/encrypt-storage@latest/dist/index.js"></script>
  <script>
    const encryptStorage = new EncryptStorage('secret-key-value');
  </script>
</body>

Options

The options object is optional and consists of the following properties:

| Property name | Default | Type | required | | -------------------- | -------------- | ----------------------------------- | -------- | | prefix | '' | string | false | | storageType | localStorage | StorageType | false | | encAlgorithm | AES | EncAlgorithm | false | | notifyHandler | undefined | NotifyHandler | false | | stateManagementUse | false | boolean | false | | doNotEncryptValues | false | boolean | false | | doNotParseValues | false | boolean | false |

Usage

Conventions

Create a file containing the EncryptStorage instance in a utils folder or folder of your choice. It is recommended to use it as a singleton for better use of the library.

Directory Layout

📦 src
 ┣ 📂 utils
 ┃ ┗ 📜 storage.ts
 ┗ 📜 index.ts
 ...

Parameters

secretKey: required = A string containing at least 10 characters;

NOTE: If you are using a SPA model (vue, react or angular) prefer to store this information in your application's .env file.

options: optional = An object as described above and which will be shown below;

CommonJS

const { EncryptStorage } = require('encrypt-storage');

// Example of secret_key variable in an .env file
// const encryptStorage = new EncryptStorage(process.env.SECRET_KEY, options);
const encryptStorage = new EncryptStorage('secret-key-value', options);

module.exports = encryptStorage;

JS Import (ES6+)

import { EncryptStorage } from 'encrypt-storage';

// Example of secret_key variable in an .env file
// const encryptStorage = new EncryptStorage(process.env.SECRET_KEY, options);
export const encryptStorage = new EncryptStorage('secret-key-value', options);

Multiple instances

To use multiple instances, it is strictly necessary to pass the prefix to all of them. As shown below:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage1 = new EncryptStorage('secret-key-value', {
  prefix: '@instance1',
});

export const encryptStorage2 = new EncryptStorage('secret-key-value', {
  prefix: '@instance2',
});

encryptStorage1.setItem('any-key', 'any-value');
encryptStorage2.setItem('any-key', 'any-value');

in your storage:

| Key | Value | | -------------------- | ------------------------------------------ | | @instance1:any-key | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... | | @instance2:any-key | U2FsdGVkX1/w4QaIcyq5521ZXB5pqw2KEwOH+... |

Options implementation

prefix

default '' - is optional and is the prefix of all keys used in the selected storage as shown below:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  prefix: '@example',
});

storageType

default localStorage - is the type of storage that will be used, at the moment only localStorage and sessionStorage are allowed:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  storageType: 'sessionStorage',
});

stateManagementUse

NOTE: This property is also required for completely identical use to the browser's native. Therefore, it will not have the native library behavior when parsing data to javascript objects or type casting such as 'true' being a boolean, '2' being a number, etc.

default false - is a boolean value that, when true allows the use of it with vuex-persist and redux-persist:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  stateManagementUse: true,
});

encAlgorithm

default AES - Is the selected encryption algorithm.:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  encAlgorithm: 'Rabbit',
});

doNotEncryptValues

default false - This option NOT encrypt values, but use those options like prefix our multiple-instances.:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  doNotEncryptValues: true,
});

doNotParseValues

default false - This option NOT parse values, but use those options like prefix our multiple-instances.:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  doNotParseValues: true,
});

encryptStorage.setItem('key', JSON.stringfy({ name: 'John Doe' }));

const value = JSON.parse(encryptStorage.getItem('key')); // { name: 'John Doe' }

NOTE: This option does not JSON.stringify or JSON.parse the data, making return typing useless or unnecessary. This is similar to standard browser behavior.

notifyHandler

default undefined - is a function that is called every time another EncryptStorage function is called. Good for logging API and monitoring localStorage/sessionStorage.:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  notifyHandler: (params: NotifyHandlerParams) => console.info({ params }),
});

console:

{
  params: {
    type: 'get'
    key: 'any-key',
    value: 'any-value',
    index: 1,
  }
}

OBS: Check NotifyHandlerParams for more information.

Methods

From here, we will have the following code as the EncryptStorage instance model:

import { EncryptStorage } from 'encrypt-storage';

export const encryptStorage = new EncryptStorage('secret-key-value', {
  prefix: '@example',
});

setItem

Add key and encrypted value to selected storage.

encryptStorage.setItem('token', 'edbe38e0-748a-49c8-9f8f-b68f38dbe5a2');
encryptStorage.setItem(
  'token-not-encrypted',
  'edbe38e0-748a-49c8-9f8f-b68f38dbe5a2',
  true,
);

in your storage:

| Key | Value | | ------------------------------ | ------------------------------------------ | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... | | @example:token-not-encrypted | edbe38e0-748a-49c8-9f8f-b68f38dbe5a2 |

setMultipleItems

Add keys and encrypted values to selected storage.

encryptStorage.setMultipleItems([
  ['token', 'edbe38e0-748a-49c8-9f8f-b68f38dbe5a2'],
  [
    'user',
    {
      id: '123456',
      name: 'John Doe',
    },
  ],
]);

in your storage:

| Key | Value | | ---------------- | ------------------------------------------ | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... | | @example:user | U2FsdGVkX1/tT67hnb*\afcb... |

getItem

Returns the value decrypted or undefined by the key passed by parameter. Default type is any;

NOTE: It is possible to pass a generics (typescript case) to obtain a consistent and typed return for better use in the typescript.

const value = encryptStorage.getItem<T = any>('token');
const value2 = encryptStorage.getItem<T = any>('token-not-encrypted', true);

result of getItem:

const value = 'edbe38e0-748a-49c8-9f8f-b68f38dbe5a2';
const value2 = 'edbe38e0-748a-49c8-9f8f-b68f38dbe5a2';

getMultipleItems

Returns the key value pairs decrypted or undefined by the keys passed by parameter.;

const value = encryptStorage.getMultipleItems(['token', 'user', 'any-key']);

result of getMultipleItems:

const value = {
  token: 'edbe38e0-748a-49c8-9f8f-b68f38dbe5a2',
  user: {
    id: '123456',
    name: 'John Doe',
  },
  'any-key': undefined,
};

removeItem

Remove item from selected storage.

in your storage:

| Key | Value | | ---------------- | ------------------------------------------ | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

encryptStorage.removeItem('token');

now in your storage:

| Key | Value | | --- | ----- | | | |

removeMultipleItems

Remove items from selected storage.

in your storage:

| Key | Value | | ---------------- | ------------------------------------------ | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... | | @example:user | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

encryptStorage.removeMultipleItems(['token', 'user']);

now in your storage:

| Key | Value | | --- | ----- | | | |

getItemFromPattern

Returns an object containing the original keys (no prefix) and decrypted values or undefined when no value found.

in your storage:

| Key | Value | | ---------------------------- | ------------------------------------------ | | @example:fruit:apple | U2FsdGVkX1/2KEwOH+w4QaIc | | @example:fruit:grape | U2FsdGVkX1/yq5521ZXB5pqw | | @example:vegetable:lettuce | U2FsdGVkX1/tT67hnb*\afcb | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

const values = encryptStorage.getItemFromPattern('fruit');

result of getItemFromPattern:

const values = {
  'fruit:apple': 'apple',
  'fruit:grape': 'grape',
};

removeItemFromPattern

Removes all items that have the pattern passed by parameter from the selected storage.

in your storage:

| Key | Value | | ---------------------------- | ------------------------------------------ | | @example:fruit:apple | U2FsdGVkX1/2KEwOH+w4QaIc | | @example:fruit:grape | U2FsdGVkX1/yq5521ZXB5pqw | | @example:vegetable:lettuce | U2FsdGVkX1/tT67hnb*\afcb | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

encryptStorage.removeItemFromPattern('fruit');

now in your storage:

| Key | Value | | ---------------------------- | ------------------------------------------ | | @example:vegetable:lettuce | U2FsdGVkX1/tT67hnb*\afcb | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

key

Returns the key corresponding to the index passed by parameter or null.

in your storage:

| Key | Value | | ---------------------------- | ------------------------------------------ | | @example:vegetable:lettuce | U2FsdGVkX1/tT67hnb*\afcb | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

const key = encryptStorage.key(0);

result of key:

'@example:vegetable:lettuce'

length

Returns the amount of values from the selected storage.

in your storage:

| Key | Value | | ---------------------------- | ------------------------------------------ | | @example:vegetable:lettuce | U2FsdGVkX1/tT67hnb*\afcb | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

const length = encryptStorage.length;

result of length:

2

clear

Removes all keys and values from the selected storage.

in your storage:

| Key | Value | | ---------------------------- | ------------------------------------------ | | @example:vegetable:lettuce | U2FsdGVkX1/tT67hnb*\afcb | | @example:token | U2FsdGVkX1/2KEwOH+w4QaIcyq5521ZXB5pqw... |

encryptStorage.clear();

now in your storage:

| Key | Value | | --- | ----- | | | |

encryptString

Encrypts a string passed by parameter.

const value = encryptStorage.encryptString('John Doe');

result of encryptString:

const value = 'U2FsdGVkX1/tT67hnb*afcb';

decryptString

Decrypts a string passed by parameter.

const value = encryptStorage.decryptString('U2FsdGVkX1/tT67hnb*afcb');

result of decryptString:

const value = 'John Doe';

encryptValue

Encrypts a value passed by parameter.

const value = encryptStorage.encryptValue({
  id: '123456',
  name: 'John Doe',
});

result of encryptValue:

const value = 'U2FsdGVkX1/tT67hnb*afcb';

decryptValue

Decrypts a string passed by parameter.

// Using typescript
interface User {
  id: string;
  name: string;
}

const value = encryptStorage.decryptValue<User>('U2FsdGVkX1/tT67hnb*afcb');

result of decryptValue:

const value = {
  id: '123456',
  name: 'John Doe',
};

hash

Encrypts a string passed by parameter with SHA256 encryptation.

const value = encryptStorage.hash('John Doe');

result of hashed value:

const value =
  '52bec733f066a11182798f4defec648ea00e374a1cda73111a443b295fd8e028';

md5Hash

Encrypts a string passed by parameter with MD5 encryptation.

const value = encryptStorage.md5Hash('John Doe');

result of hashed value:

const value = '284e512750fb7d41f1cc5284a2c56a13';

NextJS

When used in NextJS, validation must be done.

example:

// utils/storage.(ts|js)
import { EncryptStorage } from 'encrypt-storage';

const encryptStorage = (): EncryptStorage | null => {
  const isInClientSide =
    typeof window !== 'undefined' && typeof window?.self !== 'undefined';

  if (isInClientSide) {
    return new EncryptStorage(
      String(process.env.NEXT_PUBLIC_STORAGE_SECRET),
      // options,
    );
  }

  return null;
};

usage:

'use client';
import { encryptStorage } from '../utils/storage.ts';

// ...rest of code
encryptStorage()?.setItem('any-key', { name: 'John Doe', age: 40 });

AsyncEncryptStorage

EncryptStorage can also be used asynchronously, simply using its corresponding version already exported by the library.

NOTE: This functionality has its usefulness revealed in the context of redux-persist, shown below.

example:

import { AsyncEncryptStorage } from 'encrypt-storage';

export const encryptStorage = new AsyncEncryptStorage('secret-key-value', options);

async function getDecryptedValue('key'): Promise<any | undefined> {
  const value = await encryptStorage.getItem('key');
}

AWS Amplify

In the case of aws-amplify, if you want to use the facility of not needing to use JSON.parse in the rest of the application, prefer to create an instance within the amplify configuration file, as follows:

import Amplify from 'aws-amplify';
import { EncryptStorage } from 'encrypt-storage';

const encryptStorage = new EncryptStorage('secret-key-value', {
  ...,
  stateManagementUse: true,
});

...

Amplify.configure({
  Auth: {
    ...,
    storage: encryptStorage,
  },
});

State Management Persisters

This library can be used to encrypt data from state management persisters like vuex-persist, redux-persist and pinia-plugin-persist. Below are their respective implementations:

NOTE: the stateManagementUse option must be used in the EncryptStorage instance to work correctly.

vuex-persist

import VuexPersistence from 'vuex-persist';

import { encryptStorage } from 'path/to/encryptStorage';

const vuexLocal = new VuexPersistence<RootState>({
  storage: encryptStorage,
});

redux-persist

// ...
import { AsyncEncryptStorage } from 'encrypt-storage';

export const encryptStorage = new AsyncEncryptStorage('secret-key-value', options);

const persistConfig = {
  key: 'root',
  storage: encryptStorage,
  whitelist: ['navigation'],
  ...
};

pinia-plugin-persist

// ...
import { encryptStorage } from 'path/to/encryptStorage';

export const useUserStore = defineStore('storeUser', {
  state() {
    return {
      firstName: 'S',
      lastName: 'L',
      accessToken: 'xxxxxxxxxxxxx',
    };
  },
  persist: {
    enabled: true,
    strategies: [
      {
        storage: encryptStorage,
        paths: ['accessToken'],
      },
    ],
  },
});

pinia-plugin-persistedstate

import { defineStore } from 'pinia'
import { encryptStorage } from 'path/to/encryptStorage';

export const useStore = defineStore('store', {
  state: () => ({
    return: {
      first: 'John',
      last: 'Doe',
      accessToken: 'xxxxxxxxxxxxx'.
    },
  }),
  persist: {
    storage: encryptStorage,
    paths: ['accessToken'],
  },
});

License

MIT License