什麼是 AES 對稱加密演算法?
AES(Advanced Encryption Standard)是一種對稱加密算法,它是目前最常用的加密算法之一。它的目的是保護數據的安全性和隱私,可以應用於各種場合,例如在互聯網上安全傳輸數據,存儲敏感數據等等。
AES算法使用相同的密鑰來加密和解密數據,因此被稱為“對稱加密算法”。它的加密過程包括以下步驟:
- 密鑰擴展:將輸入的密鑰擴展為更長的密鑰序列,以供後續的加密和解密過程使用。
- 初始輪:將明文數據按照一定的規則與密鑰序列進行異或操作。
- 輪函數:重覆執行多輪操作,每一輪都包括四個步驟:
- 字節替換:將數據中的每個字節替換為另一個字節,使用一個固定的S盒進行映射。
- 行移位:將數據矩陣中的每一行循環左移不同的偏移量。
- 列混淆:將數據矩陣中的每一列進行混淆。
- 密鑰加:將密鑰序列中的一部分與數據進行異或操作。
- 最終輪:最後一輪操作中,省略列混淆步驟,只包括字節替換、行移位和密鑰加。
- 輸出:輸出加密後的數據。
解密過程與加密過程類似,只是在輪函數中的操作順序和密鑰序列不同。
AES算法可以使用不同的密鑰長度和不同的輪數來進行加密,較長的密鑰和更多的輪數可以提高安全性,但也會增加計算覆雜度。目前,AES算法支持128位、192位和256位密鑰長度,以及10、12和14輪加密操作。
PHP 實作 AES 加解密
PHP 實作 AES 加密 (encrypt.php)
<?php
// 定義要加密的字串
$text = "這是一個需要加密的字串";
// 定義密鑰和 IV
$key = "0123456789abcdef0123456789abcdef";
$iv = "0000000000000000";
// 定義加密方式、加密模式、填充方式
$cipher = "aes-256-cbc";
$options = OPENSSL_RAW_DATA;
// 加密字串
$encrypted = openssl_encrypt($text, $cipher, $key, $options, $iv);
// 轉換加密後的字串成為 base64 格式
$encrypted_base64 = base64_encode($encrypted);
// 輸出加密後的字串
echo $encrypted_base64;
PHP 實作 AES 解密 (descrypt.php)
<?php
// 定義要解密的字串
$encrypted_base64 = "0EmVS69YUBCibylCWo3SFW5qtM7YU/rRXHnrIsewMErikpR8y9ZfnNjm/zYh8GCA";
// 定義密鑰和 IV
$key = "0123456789abcdef0123456789abcdef";
$iv = "0000000000000000";
// 定義加密方式、加密模式、填充方式
$cipher = "aes-256-cbc";
$options = OPENSSL_RAW_DATA;
// 將加密後的字串解碼成二進位資料
$encrypted = base64_decode($encrypted_base64);
// 解密字串
$decrypted = openssl_decrypt($encrypted, $cipher, $key, $options, $iv);
// 輸出解密後的字串
echo $decrypted;
NodeJS 實作 AES 加解密
NodeJS 實作 AES 加密 (encrypt.js)
var CryptoJS = require("crypto-js");
// 定義要加密的字串
const text = "這是一個需要加密的字串";
const key = '0123456789abcdef0123456789abcdef'
const iv = '0000000000000000'
const cipher = CryptoJS.AES.encrypt(text, CryptoJS.enc.Utf8.parse(key), {
iv: CryptoJS.enc.Utf8.parse(iv), // parse the IV
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
})
console.log(cipher.toString())
NodeJS 實作 AES 解密 (decrypt.js)
var CryptoJS = require("crypto-js");
const key = '0123456789abcdef0123456789abcdef'
const iv = '0000000000000000'
const ciphertext = CryptoJS.enc.Base64.parse("0EmVS69YUBCibylCWo3SFW5qtM7YU/rRXHnrIsewMErikpR8y9ZfnNjm/zYh8GCA");
const encryptedCP = CryptoJS.lib.CipherParams.create({
ciphertext: ciphertext,
formatter: CryptoJS.format.OpenSSL
});
const decryptedWA = CryptoJS.AES.decrypt(
encryptedCP,
CryptoJS.enc.Utf8.parse(key), {
iv: CryptoJS.enc.Utf8.parse(iv)
});
const decryptedUtf8 = decryptedWA.toString(CryptoJS.enc.Utf8);
console.log(decryptedUtf8)
瀏覽器內建 TextEncoder/TexrDecoder 實作
瀏覽器內建 TextEncoder/TexrDecoder 實作加密
// Convert the data from a UTF-8 string to a byte array
const data = new TextEncoder().encode("這是一個需要加密的字串")
// Convert the key and IV from UTF-8 strings to byte arrays
const key = new TextEncoder().encode('0123456789abcdef0123456789abcdef');
const iv = new TextEncoder().encode('0000000000000000');
// Create a new AES cipher with key and IV
window.crypto.subtle.importKey(
"raw",
key,
{ name: "AES-CBC", length: 256 },
false,
["encrypt"]
).then(function(cipher) {
// Pad the data to a multiple of 16 bytes
const padding = 16 - (data.length % 16);
const paddedData = new Uint8Array(data.length + padding);
paddedData.set(data);
paddedData.fill(padding, data.length);
// Encrypt the padded data using the AES cipher and CBC mode
window.crypto.subtle.encrypt(
{ name: "AES-CBC", iv },
cipher,
paddedData
).then(function (encryptedDataBuffer) {
const encrypted = btoa(String.fromCharCode(...new Uint8Array(encryptedDataBuffer)))
console.log(encrypted)
});
});
瀏覽器內建 TextEncoder/TexrDecoder 實作解密
var encryptedData = "0EmVS69YUBCibylCWo3SFW5qtM7YU/rRXHnrIsewMErikpR8y9ZfnNjm/zYh8GCA"
const key = new TextEncoder().encode('0123456789abcdef0123456789abcdef')
const iv = new TextEncoder().encode('0000000000000000')
window.crypto.subtle.importKey(
"raw",
key,
{ name: "AES-CBC", length: 256 },
false,
["decrypt"]
).then(function(cipher) {
encryptedData = atob(encryptedData);
const encryptedDataArray = new Uint8Array(
encryptedData.length
);
for (let i = 0; i < encryptedData.length; i++) {
encryptedDataArray[i] = encryptedData.charCodeAt(i);
}
window.crypto.subtle.decrypt(
{ name: "AES-CBC", iv },
cipher,
encryptedDataArray
).then(function (decryptedDataBuffer) {
console.log(new TextDecoder().decode(decryptedDataBuffer))
})
})
References
延伸推薦