どれだけニーズがあるのかわからないが、データベースに入ってる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 raw = 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結果が毎回変わることが正な場合もある(というか本来の目的ではそちらのほうが正?)ので気をつけて下さい。
それについては上記のコードが参考になると思います。
というか僕が参考にしました。