Are you exposing your localStorage data ?
lets encrypt/decrypt our local Storage in Zustand. saving it from potential security issue!
prerequisite : Reactjs and zustand
here we will see how we can decrypt our localStorage data in the zustand.
Zustand : It's state management library like redux or RTK.
first let see how our normal global state look like. consider it as a simple todo project .
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
export const useStore = create(
persist(
(set, get) => ({
tasks: [],
logout: false,
createNewTaskFlag: false,
createNewTask: (task) =>
set((state) => ({ tasks: [task, ...state.tasks] })),
updateTaskFlag: (flag) => set({ createNewTaskFlag: flag }),
updateLogout: (flag) => set({ logout: flag }),
deleteTask: (task) =>
set((state) => {
const newTasks = state.tasks.filter((el) => el.postId !== task.postId)
return { tasks: newTasks }
}),
setTasks: (tasks) => set({ tasks: tasks }),
clearStorage: () => {
sessionStorage.removeItem('store1')
},
}),
{
name: 'store1', // storage name
storage : localStorage //saving to localStorage
}
)
)
i'm hoping that now you are familiar with this code.
lets start our main goal : )
crypto-js : we will use this lib to decrypt and encrypt our data.
Approach
we will use three fxn inside the createJsonStorage from 'zustand/middleware'
setItem : we will encrypt the data and set it to local Storage
getItem : we will get encrypted data from local Storage and decrypt it.
removeItem : (optional) to remove data from local Storag
this encrytion/decryption work like a wrapper.
what's this means : we are able to access our data as normal we used to do.
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'
import { enc, AES } from 'crypto-js'
const secretKey = process.env.REACT_APP_ENCRYPTION_KEY
const encrypt = (data) => {
return AES.encrypt(JSON.stringify(data), secretKey).toString()
}
const decrypt = (encryptedData) => {
const bytes = AES.decrypt(encryptedData, secretKey)
return JSON.parse(bytes.toString(enc.Utf8))
}
export const useStore = create(
persist(
(set, get) => ({
tasks: [],
logout: false,
createNewTaskFlag: false,
createNewTask: (task) =>
set((state) => ({ tasks: [task, ...state.tasks] })),
updateTaskFlag: (flag) => set({ createNewTaskFlag: flag }),
updateLogout: (flag) => set({ logout: flag }),
deleteTask: (task) =>
set((state) => {
const newTasks = state.tasks.filter((el) => el.postId !== task.postId)
return { tasks: newTasks }
}),
setTasks: (tasks) => set({ tasks: tasks }),
clearStorage: () => {
localStorage.removeItem('store1')
},
}),
{
name: 'store1',
storage: createJSONStorage(() => ({
getItem: (key) => {
// get data
const encryptedData = localStorage.getItem(key)
// decrypt it
return encryptedData ? decrypt(encryptedData) : null
},
setItem: (key, data) => {
// before storing it first decrypt it
const encryptedData = encrypt(data)
// now store it
localStorage.setItem(key, encryptedData)
},
removeItem: (key) => localStorage.removeItem(key),
})),
}
)
)
Now the encryption and decryption is completed. let me show you the result
As you can see that in localstorage there is 'store1' and its value is encryted.
if you like it then please share it with your friends.
Thank you