Tech note

備忘録

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

使用する拡張機能

crypto

ハッシュ化と暗号化

ハッシュ化

元となるデータをハッシュアルゴリズムによって、固定長の値に不可逆変換をすること。

暗号化

元となるデータを暗号化アルゴリズムによって、復号可能な値に変換をすること。

ハッシュ化する方法

const sha256 = crypto.createHash("sha256");
sha256.update(ハッシュ化したい値);
sha256.digest("hex");

暗号化する方法

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は、ランダムな文字列を生成して格納。

復号化する方法

const key: Uint8Array = new Buffer(暗号化の際に使用したkeyValue, "utf-8");
const iv: Uint8Array = new Buffer(暗号化の際に使用したivValue, "utf-8");
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
let decipheredData = decipher.update(暗号化した値, "hex", "utf8");
decipheredData += decipher.final("utf8");

作成した画面のスクリーンショット

f:id:sbu8:20200822154408p:plain

全体のソースコード

<template>
  <div>
    <v-text-field
      v-model="inputHash"
      label="ハッシュ値に変換したい文字列"
    >
    </v-text-field>
    <v-btn @click="convertHash">ハッシュ変換</v-btn>
    <div>ハッシュ値: {{ outputHash }}</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>
    <v-text-field
      v-model="inputDecrypto"
      label="復号化したい暗号化値"
    >
    </v-text-field>
    <v-text-field
      v-model="inputKey"
      label="Key"
    >
    </v-text-field>
    <v-text-field
      v-model="inputIv"
      label="Initial Vector"
    >
    </v-text-field>
    <v-btn @click="convertDecrypto">復号化</v-btn>
    <div>復号化: {{ outputDecrypto }}</div>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator";
const crypto = require("crypto");

@Component({})
export default class extends Vue {
  private inputHash: string = "";
  private outputHash: string = "";
  private inputCrypto: string = "";
  private outputCrypto: string = "";
  private useCryptoKeyValue: string = "";
  private useCryptoIvValue: string = "";
  private inputDecrypto: string = "";
  private inputKey: string = "";
  private inputIv: string = "";
  private outputDecrypto: string = "";

  private convertHash(): void {
    const sha256 = crypto.createHash("sha256");
    sha256.update(this.inputHash);
    this.outputHash = sha256.digest("hex");
  }

  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;
  }

  private convertDecrypto(): void {
    const key: Uint8Array = new Buffer(this.inputKey, "utf-8");
    const iv: Uint8Array = new Buffer(this.inputIv, "utf-8");
    const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
    let decipheredData = decipher.update(this.inputDecrypto, "hex", "utf8");
    decipheredData += decipher.final("utf8");
    this.outputDecrypto = decipheredData;
  }

}
</script>