Edited at

Node.jsで文字列を暗号化・復号する 【string encryption in node.js】

どれだけニーズがあるのかわからないが、データベースに入ってるidとかを必要な時に難読化したかった。

例えば、example.com/1/profileみたいなURLだと、「1のところを2に変えたら他の人のプロフィール見えるんじゃないの」みたいなのをトライできないようにしたい。

で、とりあえずstringを入力したらそいつをencryptした文字列を返却するモジュールを作ってみよう。

加えて、Adminの立場的にはencryptされた文字列を見るのはめんどくさいのでdecryptもできるようにしよう。

nodeにはcryptoという暗号化周りの組み込みモジュールが存在するので、そいつを利用する。

ドキュメント: https://nodejs.org/api/crypto.html

const crypto = require('crypto');

const ENCRYPTION_KEY = "HH95XH7sYAbznRBJSUE9W8RQxzQIGSpy" // 32Byte. このまま利用しないこと!
const BUFFER_KEY = "RfHBdAR5RJHqp5wm" // 16Byte. このまま利用しないこと!
const ENCRYPT_METHOD = "aes-256-cbc" // 暗号化方式
const ENCODING = "hex" // 暗号化時のencoding

const rawString = JSON.stringify({userId: 1}) // 暗号化する対象。stringなら何でも。

function getEncryptedString(raw) {
let iv = Buffer.from(BUFFER_KEY)
let cipher = crypto.createCipheriv(ENCRYPT_METHOD, Buffer.from(ENCRYPTION_KEY), iv)
let encrypted = cipher.update(raw)

encrypted = Buffer.concat([encrypted, cipher.final()])

return encrypted.toString(ENCODING)
}

function getDecryptedString(encrypted) {
let iv = Buffer.from(BUFFER_KEY)
let encryptedText = Buffer.from(encrypted, ENCODING)
let decipher = crypto.createDecipheriv(ENCRYPT_METHOD, Buffer.from(ENCRYPTION_KEY), iv)
let decrypted = decipher.update(encryptedText)

decrypted = Buffer.concat([decrypted, decipher.final()])

return decrypted.toString()
}

// 以下は試してみてるだけ

console.log(`raw: ${raw}`)

const encrypted = getEncryptedString(raw)

console.log(`encrypted: ${encrypted}`)

const decrypted = getDecryptedString(encrypted)

console.log(`decrypted: ${decrypted}`)

上記をコピペして適当なファイル名(encryption-sample.js とか)をつけて、node encryption-sample.jsを叩くと下記のようなアウトプットになるはず

raw: {"userId":1}

encrypted: e3629d8ff7295f693569359d06fd4da2
decrypted: {"userId":1}

今回は、getEncryptedString()に対してあるstring: Aを渡した場合に、どんな場合でも同じ結果string: A'が返ってきてほしかったので、let iv = Buffer.from(BUFFER_KEY)の部分で必ず同じiv (= initialization vector)が生成されるようにしています。

ただし、用途によっては毎回異なるivを生成し、encryption結果が毎回変わることが正な場合もある(というか本来の目的ではそちらのほうが正?)ので気をつけて下さい。

https://gist.github.com/vlucas/2bd40f62d20c1d49237a109d491974eb

それについては上記のコードが参考になると思います。

というか僕が参考にしました。