Last active
April 24, 2024 02:08
-
-
Save iamnivekx/af067fe0d2af0d71fbdee0f2645672aa to your computer and use it in GitHub Desktop.
encrypt and decrypt the text using the password.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is used to encrypt and decrypt the text using the password. | |
* The password is used to derive the key using PBKDF2. | |
* The key is used to encrypt and decrypt the text using AES-GCM. | |
* The salt is used to derive the key using PBKDF2. | |
* The nonce is used to encrypt and decrypt the text using AES-GCM. | |
* The ciphertext is the encrypted text. | |
* The salt, nonce, and ciphertext are concatenated and converted to Base64. | |
* inspire by https://github.com/MetaMask/metamask-extension/blob/develop/app/scripts/controllers/user-storage/encryption.ts | |
*/ | |
import { gcm } from '@noble/ciphers/aes'; | |
import { randomBytes } from '@noble/ciphers/webcrypto'; | |
import { pbkdf2, Pbkdf2Opt } from '@noble/hashes/pbkdf2'; | |
import { sha256 } from '@noble/hashes/sha256'; | |
import { concatBytes, utf8ToBytes } from '@noble/hashes/utils'; | |
const ALGORITHM_KEY_SIZE = 16; | |
const ALGORITHM_NONCE_SIZE = 12; | |
const PBKDF2_SALT_SIZE = 16; | |
const PBKDF2_ITERATIONS = 900_000; | |
const pbkdf2Opt: Pbkdf2Opt = { c: PBKDF2_ITERATIONS, dkLen: ALGORITHM_KEY_SIZE }; | |
export function bytesToBase64(byteArray: Uint8Array) { | |
return Buffer.from(byteArray).toString('base64'); | |
} | |
export function base64ToBytes(base64: string) { | |
return new Uint8Array(Buffer.from(base64, 'base64')); | |
} | |
export function bytesToUtf8(bytes: Uint8Array) { | |
// if (typeof bytes !== 'string') throw new Error(`bytesToUtf8 expected string, got ${typeof str}`); | |
const decoder = new TextDecoder('utf-8'); | |
return decoder.decode(bytes); | |
} | |
/** | |
* This function is used to encrypt the text with the key | |
* @param text: the text to encrypt, it can be any string. | |
* @param password: the password, it can be any string. | |
* @returns [salt(PBKDF2_SALT_SIZE bytes)][nonce(ALGORITHM_NONCE_SIZE bytes)][ciphertext(? bytes)] | base64 | |
*/ | |
export function encrypt(text: string, password: string) { | |
// prepend salt. | |
const salt = randomBytes(PBKDF2_SALT_SIZE); | |
// Derive a key using PBKDF2. | |
const key = pbkdf2(sha256, password, salt, pbkdf2Opt); | |
// prepend salt. | |
const plaintext = utf8ToBytes(text); | |
// prepend nonce. | |
const nonce = randomBytes(ALGORITHM_NONCE_SIZE); | |
// Encrypt | |
const encrypted = gcm(key, nonce).encrypt(plaintext); | |
const ciphertextAndNonceAndSalt = concatBytes(salt, nonce, encrypted); | |
// Convert to Base64 | |
return bytesToBase64(ciphertextAndNonceAndSalt); | |
} | |
/** | |
* This function is used to decrypt the text with the key | |
* @param text: encrypted text, it should be base64. | |
* @param password: the password, it can be any string. | |
* @returns: the decrypted text. | |
*/ | |
export function decrypt(text: string, password: string) { | |
// Decode the base64. | |
const ciphertextAndNonceAndSalt = base64ToBytes(text); | |
// Create buffers of salt nonce and ciphertext. | |
// [salt(PBKDF2_SALT_SIZE bytes)][nonce(ALGORITHM_NONCE_SIZE bytes)][ciphertext(? bytes)] | |
const salt = ciphertextAndNonceAndSalt.slice(0, PBKDF2_SALT_SIZE); | |
const nonce = ciphertextAndNonceAndSalt.slice(PBKDF2_SALT_SIZE, PBKDF2_SALT_SIZE + ALGORITHM_NONCE_SIZE); | |
const ciphertext = ciphertextAndNonceAndSalt.slice(PBKDF2_SALT_SIZE + ALGORITHM_NONCE_SIZE, ciphertextAndNonceAndSalt.length); | |
// Derive the key using PBKDF2. | |
const key = pbkdf2(sha256, password, salt, pbkdf2Opt); | |
// Decrypt the ciphertext. | |
const decrypted = gcm(key, nonce).decrypt(ciphertext); | |
// Return result. | |
return bytesToUtf8(decrypted); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment