Skip to content

Instantly share code, notes, and snippets.

@rhrn
Last active August 2, 2023 19:43
Show Gist options
  • Save rhrn/8971e0d9c423a772f0b6467ffd9af53f to your computer and use it in GitHub Desktop.
Save rhrn/8971e0d9c423a772f0b6467ffd9af53f to your computer and use it in GitHub Desktop.
Encrypt your data with your password with web encryption and nodejs using prompts

Nodejs

Encrypt your raw text (seed phrase, text, ...) with password

node enc.mjs

Decrypt encrypted base64 data with your password

node dec.mjs
Example
> node enc.mjs
password for encrypt: hi
seed phrase: a b c d
base64: HGky6RP7039MGEYkLGHhOYA7RXQmtbE=

> node dec.mjs
password for decrypt: hi
encrypted base64 data: HGky6RP7039MGEYkLGHhOYA7RXQmtbE=
original:  a b c d

Web based

copy enc.web.mjs content and paste in browser's console launch in console

enc()

copy dec.web.mjs content and paste in browser's console launch in console

dec()
import * as util from 'util'
import * as readline from 'readline'
import { webcrypto } from 'node:crypto'
import { stdin as input, stdout as output } from 'process'
const { subtle } = webcrypto
const rl = readline.createInterface({ input, output })
rl.input.on('keypress', (c) => {
if (c.charCodeAt() === 127) {
const len = rl.line.length
readline.moveCursor(rl.output, -len, 0)
readline.clearLine(rl.output, 1)
return
}
readline.moveCursor(rl.output, -1, 0)
readline.clearLine(rl.output, 1)
})
const question = util.promisify(rl.question).bind(rl)
;(async () => {
try {
let password = await question('password for decrypt: ')
password = password.trim()
let data = await question('encrypted base64 data: ')
data = data.trim()
const encoder = new TextEncoder()
const keyMaterial = await subtle.importKey(
'raw',
encoder.encode(password),
'PBKDF2',
false,
['deriveKey', 'deriveBits']
)
const salt = encoder.encode(password)
const bits = await subtle.deriveBits({
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations: 1000
}, keyMaterial, 256)
const key = await subtle.deriveKey(
{
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations: 100,
},
keyMaterial,
{
name: 'AES-GCM',
length: 256,
},
true,
['encrypt', 'decrypt']
)
const ciphertext = Buffer.from(data, 'base64')
const decrypted = await subtle.decrypt(
{
name: 'AES-GCM',
iv: bits
},
key,
ciphertext
)
const decoder = new TextDecoder()
console.log('original: ', decoder.decode(decrypted))
} catch (err) {
console.error('rejected', err)
}
process.exit(1)
})()
const { subtle } = crypto
const iterations = 1000;
const dec = async () => {
try {
let password = await prompt('password for decrypt: ')
password = password.trim()
let data = await prompt('encrypted base64 data: ')
data = data.trim()
const encoder = new TextEncoder()
const keyMaterial = await subtle.importKey(
'raw',
encoder.encode(password),
'PBKDF2',
false,
['deriveKey', 'deriveBits']
)
const salt = encoder.encode(password)
const bits = await subtle.deriveBits({
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations
}, keyMaterial, 256)
const key = await subtle.deriveKey(
{
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations
},
keyMaterial,
{
name: 'AES-GCM',
length: 256,
},
true,
['encrypt', 'decrypt']
)
const ciphertext = Uint8Array.from(atob(data), c => c.charCodeAt(0))
const decrypted = await subtle.decrypt(
{
name: 'AES-GCM',
iv: bits
},
key,
ciphertext
)
const decoder = new TextDecoder()
console.log('original: ', decoder.decode(decrypted))
} catch (err) {
console.error('Question rejected', err)
}
}
import * as util from 'util'
import * as readline from 'readline'
import { webcrypto } from 'node:crypto'
import { stdin as input, stdout as output } from 'process'
const { subtle } = webcrypto
const rl = readline.createInterface({ input, output })
rl.input.on('keypress', (c) => {
if (c.charCodeAt() === 127) {
const len = rl.line.length
readline.moveCursor(rl.output, -len, 0)
readline.clearLine(rl.output, 1)
return
}
readline.moveCursor(rl.output, -1, 0)
readline.clearLine(rl.output, 1)
})
const question = util.promisify(rl.question).bind(rl)
;(async () => {
try {
let password = await question('password for encrypt: ')
password = password.trim()
let data = await question('seed phrase: ')
data = data.trim()
const encoder = new TextEncoder()
const keyMaterial = await subtle.importKey(
'raw',
encoder.encode(password),
'PBKDF2',
false,
['deriveKey', 'deriveBits']
)
const salt = encoder.encode(password)
const bits = await subtle.deriveBits({
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations: 1000
}, keyMaterial, 256)
const key = await subtle.deriveKey(
{
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations: 100,
},
keyMaterial,
{
name: 'AES-GCM',
length: 256,
},
true,
['encrypt', 'decrypt']
)
const ciphertext = await subtle.encrypt(
{
name: 'AES-GCM',
iv: bits
},
key,
encoder.encode(data)
)
const base64 = Buffer.from(ciphertext).toString('base64')
// const hex = Buffer.from(ciphertext).toString('hex')
console.log('base64:', base64)
// console.log('hex:', hex)
} catch (err) {
console.error('rejected', err)
}
process.exit(1)
})()
const { subtle } = crypto
const iterations = 1000
const enc = async () => {
try {
let password = await prompt('password for encrypt: ')
password = password.trim()
let data = await prompt('seed phrase: ')
data = data.trim()
const encoder = new TextEncoder()
const keyMaterial = await subtle.importKey(
'raw',
encoder.encode(password),
'PBKDF2',
false,
['deriveKey', 'deriveBits']
)
const salt = encoder.encode(password)
const bits = await subtle.deriveBits({
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations
}, keyMaterial, 256)
const key = await subtle.deriveKey(
{
name: 'PBKDF2',
hash: 'SHA-512',
salt,
iterations
},
keyMaterial,
{
name: 'AES-GCM',
length: 256,
},
true,
['encrypt', 'decrypt']
)
const ciphertext = await subtle.encrypt(
{
name: 'AES-GCM',
iv: bits
},
key,
encoder.encode(data)
)
const base64 = btoa(String.fromCharCode(...new Uint8Array(ciphertext)))
console.log('base64:', base64)
} catch (err) {
console.error('Question rejected', err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment