DEV Community

Cover image for Encypher : Secure Your React State with Encrypted localStorage and sessionStorage
Sreehari S J
Sreehari S J

Posted on

Encypher : Secure Your React State with Encrypted localStorage and sessionStorage

As developers, we often store user preferences, tokens, and other sensitive data in the browser. But how secure is your localStorage or sessionStorage? Enter Encypher – a lightweight React hook that brings AES-GCM encryption to your front-end state management with an easy useState-like API. Let’s dive in!


Why You Need Encrypted Storage in React

React makes state management easy, but storing data directly in the browser can be risky:

  • Tokens and session info are vulnerable to XSS attacks.
  • localStorage/sessionStorage is plaintext by default.
  • Legacy fallback mechanisms often sacrifice security.

Encypher solves this by encrypting data with AES-GCM and providing optional XOR fallback for legacy browsers. You can also set a time-to-live (TTL) for auto-expiring storage.


Key Features of Encypher

  • AES-GCM encryption using the Web Crypto API.
  • Custom secret per hook or global via EncryptedStorageProvider.
  • Optional TTL for expiring sensitive data.
  • Works with localStorage, sessionStorage, or custom storage.
  • Syncs across tabs/windows.
  • XOR fallback for legacy browsers (not secure).
  • Simple API: [value, setValue, remove, reencrypt].
  • Tested with React 17/18.

Installation

npm install encypher
# or
yarn add encypher
Enter fullscreen mode Exit fullscreen mode

Then import the hook into your React component:

import { useEncryptedStorage } from "encypher";
Enter fullscreen mode Exit fullscreen mode

VS Code ScreenShot

Basic Usage Example

import { useEncryptedStorage } from "encypher";

function MyComponent() {
  const [user, setUser, removeUser] = useEncryptedStorage("user", null, {
    secret: "my-strong-secret",
    storage: "local", // "session" is also supported
    ttl: 3600 * 1000, // 1 hour TTL
  });

  return (
    <div>
      <button onClick={() => setUser({ name: "John Doe" })}>
        Store User
      </button>
      <button onClick={removeUser}>Remove User</button>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Tip: Treat useEncryptedStorage like useState, but with encryption built-in.


Using a Global Secret with Provider

import { EncryptedStorageProvider, useEncryptedStorage } from "encypher";

function App() {
  return (
    <EncryptedStorageProvider secret="my-global-secret">
      <MyComponent />
    </EncryptedStorageProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Custom Storage

const customStorage = {
  getItem: (key) => window.localStorage.getItem(key),
  setItem: (key, value) => window.localStorage.setItem(key, value),
  removeItem: (key) => window.localStorage.removeItem(key),
};

const [data, setData] = useEncryptedStorage("key", {}, {
  secret: "my-secret",
  storage: customStorage
});
Enter fullscreen mode Exit fullscreen mode

API Overview

useEncryptedStorage(key, initialValue, options) returns:

[value, setValue, remove, reencrypt]
Enter fullscreen mode Exit fullscreen mode
  • value: current decrypted value
  • setValue(val): asynchronously encrypt and store
  • remove(): remove stored value
  • reencrypt(newSecret): re-encrypt existing data

Options object includes:

{
  secret,          // Required encryption key
  storage,         // "local", "session", or custom
  ttl,             // Optional expiration time
  fallback,        // "xor" for legacy fallback
  onFallback,      // Callback if fallback is used
  onError,         // Callback on error
  onReencrypt      // Callback after re-encryption
}
Enter fullscreen mode Exit fullscreen mode

Security Notes

  • Always use a strong, unique secret.
  • XOR fallback is insecure, only for non-sensitive data.
  • AES-256 keys are derived via PBKDF2.
  • Not suitable for highly sensitive or regulated data.

Demo Webpage ScreenShot

Encypher Demo Website

Test all features live on the Encypher Demo Website.

Demo Highlights:

  • Encryption & decryption with custom secrets
  • TTL-based expiry testing
  • Debug view of encrypted data
  • Real-time interactive testing

Why Encypher is Developer-Friendly

  • Easy to adopt: useState-like API means zero learning curve.
  • Flexible: Use localStorage, sessionStorage, or custom storage.
  • Secure by default: AES-GCM ensures modern encryption standards.
  • Reactive: Works seamlessly with React state updates.

Conclusion

Secure your React state in style! Whether you’re storing user tokens, preferences, or other sensitive data, Encypher makes encryption effortless.

Pro Tip: Combine Encypher with your existing state management to add a security layer without changing your workflow.

Get started today:


Follow me for more tips and tools on React and front-end development!

Top comments (2)

Collapse
 
developeraromal profile image
Aromal

Exactly what I was looking for! In Flutter we’ve got flutter_secure_storage, but for web local storage there wasn’t really a solid package out there. You’ve really filled that gap awesome work, man

Collapse
 
masterdevsabith profile image
Muhammed Sabith

❤️🔥