Nuxtで暗号化した値をブラウザのJavaScriptで復号化して再度暗号化する
環境
Nuxt
名称 | Version |
---|---|
Node | 14.5.0 |
Nuxt | 2.13.3 |
Vue | 2.6.11 |
TypeScript | 3.8.3 |
Vuetify | 2.3.3 |
nuxt-property-decorator | 2.7.2 |
ブラウザのJavaScript
名称 | Version |
---|---|
jQuery | 3.5.1 |
Bootstrap | 4.5.2 |
使用する拡張機能
Nuxt
crypto
Nuxtで暗号化する方法
const S: string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; const numArr32: number[] = Array.from(crypto.randomFillSync(new Uint8Array(32))); const numArr16: number[] = Array.from(crypto.randomFillSync(new Uint8Array(16))); const keyValue: string = numArr32.map((n: number)=>S[n%S.length]).join(""); const ivValue: string = numArr16.map((n: number)=>S[n%S.length]).join(""); const key: Uint8Array = new Buffer(keyValue, "utf-8"); const iv: Uint8Array = new Buffer(ivValue, "utf-8"); const cipher = crypto.createCipheriv("aes-256-cbc", key, iv); let encrypted = cipher.update(暗号化したい値); encrypted += cipher.final("hex");
備考
keyValueとivValueは、ランダムな文字列を生成して格納。
ブラウザのJavaScriptで復号化する方法
const inputIv = Nuxtで暗号化した値; const inputKey = Nuxtで暗号化の際に使用したkeyValueの値; const inputIv = Nuxtで暗号化の際に使用したivValueの値; const key = new TextEncoder("utf-8").encode(inputKey); const iv = new TextEncoder("utf-8").encode(inputIv); const convertUint8Arr = new Uint8Array(inputVal.match(/.{1,2}/g).map(v => parseInt(v, 16))); window.crypto.subtle.importKey( "raw", key, "AES-CBC", true, ["decrypt"] ).then(key => { window.crypto.subtle.decrypt( { name: "AES-CBC", iv }, key, convertUint8Arr ).then(element => { const decryptoVal = new TextDecoder("utf-8").decode(element); }) })
ブラウザのJavaScriptで再度暗号化する方法
const inputVal = 暗号化したい値; const inputKey = Nuxtで暗号化の際に使用したkeyValueの値; const inputIv = Nuxtで暗号化の際に使用したivValueの値; const key = new TextEncoder("utf-8").encode(inputKey); const iv = new TextEncoder("utf-8").encode(inputIv); window.crypto.subtle.importKey( "raw", key, "AES-CBC", true, ["encrypt"] ).then(key => { window.crypto.subtle.encrypt( { name: "AES-CBC", iv }, key, new TextEncoder("utf-8").encode(inputVal) ).then(element => { const cryptoVal = Array.from(new Uint8Array(element)).map(num => num.toString(16).padStart(2, "0")).join(""); }) })
作成した画面のスクリーンショット
Nuxt
ブラウザのJavaScript
全体のソースコード
Nuxt
<template> <div> <v-text-field v-model="inputCrypto" label="暗号化したい文字列" > </v-text-field> <v-btn @click="convertCrypto">暗号化</v-btn> <div>暗号化: {{ outputCrypto }}</div> <div>Key: {{ useCryptoKeyValue }}</div> <div>Initial Vector: {{ useCryptoIvValue }}</div> </div> </template> <script lang="ts"> import { Component, Vue } from "nuxt-property-decorator"; const crypto = require("crypto"); @Component({}) export default class extends Vue { private inputCrypto: string = ""; private outputCrypto: string = ""; private useCryptoKeyValue: string = ""; private useCryptoIvValue: string = ""; private convertCrypto(): void { const S: string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; const numArr32: number[] = Array.from(crypto.randomFillSync(new Uint8Array(32))); const numArr16: number[] = Array.from(crypto.randomFillSync(new Uint8Array(16))); const keyValue: string = numArr32.map((n: number)=>S[n%S.length]).join(""); const ivValue: string = numArr16.map((n: number)=>S[n%S.length]).join(""); const key: Uint8Array = new Buffer(keyValue, "utf-8"); const iv: Uint8Array = new Buffer(ivValue, "utf-8"); const cipher = crypto.createCipheriv("aes-256-cbc", key, iv); let encrypted = cipher.update(this.inputCrypto); encrypted += cipher.final("hex"); this.useCryptoKeyValue = keyValue; this.useCryptoIvValue = ivValue; this.outputCrypto = encrypted; } } </script>
ブラウザのJavaScript
html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script> <script type="text/javascript" src="./js/decrypto.js" defer="defer"></script> <title>復号化</title> </head> <body> <div class="container"> <div class="form-group"> <label for="cryptoVal">暗号化した値</label> <input type="text" id="cryptoVal" class="form-control"> </div> <div class="form-group"> <label for="cryptoKey">Key</label> <input type="text" id="cryptoKey" class="form-control"> </div> <div class="form-group"> <label for="cryptoIv">Initial Vector</label> <input type="text" id="cryptoIv" class="form-control"> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button id="decryptoBtn" class="btn btn-primary">復号化</button> </div> </div> <div class="form-group"> <label id="outputDecrypto" class="col-sm-2 control-label"></label> </div> <div class="form-group"> <label for="cryptoVal">暗号化する値</label> <input type="text" id="cryptoVal2" class="form-control"> </div> <div class="form-group"> <label for="cryptoKey">Key</label> <input type="text" id="cryptoKey2" class="form-control"> </div> <div class="form-group"> <label for="cryptoIv">Initial Vector</label> <input type="text" id="cryptoIv2" class="form-control"> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button id="cryptoBtn" class="btn btn-primary">暗号化</button> </div> </div> <div class="form-group"> <label id="outputCrypto" class="col-sm-2 control-label"></label> </div> </div> </body> </html>
JavaScript
$("#decryptoBtn").on("click", function() { const inputVal = $("#cryptoVal").val(); const inputKey = $("#cryptoKey").val(); const inputIv = $("#cryptoIv").val(); const key = new TextEncoder("utf-8").encode(inputKey); const iv = new TextEncoder("utf-8").encode(inputIv); const convertUint8Arr = new Uint8Array(inputVal.match(/.{1,2}/g).map(v => parseInt(v, 16))); window.crypto.subtle.importKey( "raw", key, "AES-CBC", true, ["decrypt"] ).then(key => { window.crypto.subtle.decrypt( { name: "AES-CBC", iv }, key, convertUint8Arr ).then(element => { const decryptoVal = new TextDecoder("utf-8").decode(element); $("#outputDecrypto").text(decryptoVal) }) }) }); $("#cryptoBtn").on("click", function() { const inputVal = $("#cryptoVal2").val(); const inputKey = $("#cryptoKey2").val(); const inputIv = $("#cryptoIv2").val(); const key = new TextEncoder("utf-8").encode(inputKey); const iv = new TextEncoder("utf-8").encode(inputIv); window.crypto.subtle.importKey( "raw", key, "AES-CBC", true, ["encrypt"] ).then(key => { window.crypto.subtle.encrypt( { name: "AES-CBC", iv }, key, new TextEncoder("utf-8").encode(inputVal) ).then(element => { const cryptoVal = Array.from(new Uint8Array(element)).map(num => num.toString(16).padStart(2, "0")).join(""); $("#outputCrypto").text(cryptoVal) }) }) });