Vue
by tranxuanthang
HTML
<div id="app">
<h1>Mã hóa và giải mã với AES-GCM</h1>
<h2>Mã hóa</h2>
Mật khẩu:<br>
<input type="password" v-model="inputPassword" /><br>
Nội dung:<br>
<textarea v-model="inputContent"></textarea><br>
<button @click="submitEncrypt">Mã hóa</button><br>
Kết quả: (click để copy)<br>
<div class="result-data">
<div class="error" v-if="errorEncrypt">
Mã hóa thất bại!
</div>
<div class="data nothing" v-else-if="resultEncrypted == ''">
Chưa có gì :(
</div>
<div class="data" v-else>
{{ resultEncrypted }}
</div>
</div>
<br>
<h2>Giải mã</h2>
Mật khẩu:<br>
<input type="password" v-model="inputPasswordDecrypt" /><br>
Dữ liệu đã mã hóa (dạng JSON):<br>
<textarea v-model="inputEncrypted"></textarea><br>
<button @click="submitDecrypt">Giải mã</button><br>
Kết quả:<br>
<div class="result-data">
<div class="error" v-if="errorDecrypt">
Giải mã thất bại!
</div>
<div class="data nothing" v-else-if="resultDecrypted == ''">
Chưa có gì :(
</div>
<div class="data" v-else>
{{ resultDecrypted }}
</div>
</div>
</div>
CSS
body {
font-size: 16px;
}
h1 {
font-size: 160%;
}
h2 {
font-size: 130%;
}
textarea {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
}
.result-data {
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: all;
user-select: all;
word-wrap: break-word;
font-family: monospace;
padding: 8px;
background-color: #eee;
}
.error {
color: red;
}
.nothing {
color: blue;
}
Vue
// https://bitcoin.stackexchange.com/questions/52727/byte-array-to-hexadecimal-and-back-again-in-javascript
const toHexString = byteArray => {
var bufferView = new Uint8Array(byteArray);
return Array.prototype.map.call(bufferView, function (byte) {
return ("0" + (byte & 0xFF).toString(16)).slice(-2);
}).join("");
};
const toByteArray = hexString => {
var result = [];
while (hexString.length >= 2) {
result.push(parseInt(hexString.substring(0, 2), 16));
hexString = hexString.substring(2, hexString.length);
}
return new Uint8Array(result);
};
const getRandomArrayBuffer = bytesNumber => {
let byte = new Uint8Array(bytesNumber);
crypto.getRandomValues(byte);
return byte;
};
const getKeyMaterial = async (passwordString) => {
const passwordBuffer = new TextEncoder().encode(passwordString);
return await crypto.subtle.importKey("raw", passwordBuffer, { name: "PBKDF2" }, false, ["deriveBits", "deriveKey"]);
};
const getKey = async (saltBuffer, keyMaterial, iterations) => {
let params = {
name: "PBKDF2",
salt: saltBuffer,
iterations: 100000,
hash: "SHA-256"
};
return await crypto.subtle.deriveKey(
params,
keyMaterial,
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
};
const encryptMessage = async (dataBuffer, key, ivBuffer) => {
return await crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: ivBuffer
},
key,
dataBuffer
);
}
const decryptMessage = async (encryptedDataBuffer, key, ivBuffer) => {
return await crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: ivBuffer
},
key,
encryptedDataBuffer
);
}
new Vue({
el: "#app",
data: {
inputPassword: "",
inputContent: "",
resultEncrypted: "",
inputPasswordDecrypt: "",
inputEncrypted: "",
resultDecrypted: "",
errorEncrypt: false,
errorDecrypt: false
},
methods: {
submitEncrypt: async function () {
try {
// Tạo khóa
...