mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
84 lines
2.2 KiB
TypeScript
84 lines
2.2 KiB
TypeScript
import { webcrypto } from 'node:crypto'
|
|
|
|
/**
|
|
* Get key material from password
|
|
*
|
|
* 从密码获取密钥材料
|
|
*
|
|
* @see https://developer.mozilla.org/zh-CN/docs/Web/API/SubtleCrypto/deriveKey#pbkdf2_2
|
|
* @param password - Password string / 密码字符串
|
|
* @returns CryptoKey / 加密密钥
|
|
*/
|
|
function getKeyMaterial(password: string) {
|
|
const enc = new TextEncoder()
|
|
return webcrypto.subtle.importKey(
|
|
'raw',
|
|
enc.encode(password),
|
|
'PBKDF2',
|
|
false,
|
|
['deriveBits', 'deriveKey'],
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Get derived key from key material
|
|
*
|
|
* 从密钥材料获取派生密钥
|
|
*
|
|
* @param keyMaterial - Key material / 密钥材料
|
|
* @param salt - Salt for key derivation / 密钥派生盐值
|
|
* @returns Derived CryptoKey / 派生加密密钥
|
|
*/
|
|
function getCryptoDeriveKey(keyMaterial: CryptoKey | webcrypto.CryptoKey, salt: Uint8Array) {
|
|
return webcrypto.subtle.deriveKey(
|
|
{
|
|
name: 'PBKDF2',
|
|
salt: salt as unknown as ArrayBuffer,
|
|
iterations: 100000,
|
|
hash: 'SHA-256',
|
|
},
|
|
keyMaterial,
|
|
{
|
|
name: 'AES-CBC',
|
|
length: 256,
|
|
},
|
|
true,
|
|
['encrypt', 'decrypt'],
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Encrypt content using AES-CBC
|
|
*
|
|
* 使用 AES-CBC 加密内容
|
|
*
|
|
* @see https://github.com/mdn/dom-examples/blob/main/web-crypto/encrypt-decrypt/aes-cbc.js
|
|
* @param content - Content to encrypt / 要加密的内容
|
|
* @param options - Encryption options / 加密选项
|
|
* @param options.password - Password for encryption / 加密密码
|
|
* @param options.iv - Initialization vector / 初始化向量
|
|
* @param options.salt - Salt for key derivation / 密钥派生盐值
|
|
* @returns Encrypted content / 加密后的内容
|
|
*/
|
|
export async function encryptContent(content: string, options: {
|
|
password: string
|
|
iv: Uint8Array
|
|
salt: Uint8Array
|
|
}) {
|
|
const { password, iv, salt } = options
|
|
const keyMaterial = await getKeyMaterial(password)
|
|
const key = await getCryptoDeriveKey(keyMaterial, salt)
|
|
|
|
const enc = new TextEncoder()
|
|
const cipherTextData = await webcrypto.subtle.encrypt(
|
|
{
|
|
name: 'AES-CBC',
|
|
iv: iv as unknown as ArrayBuffer,
|
|
},
|
|
key,
|
|
enc.encode(content),
|
|
)
|
|
|
|
return String.fromCharCode(...new Uint8Array(cipherTextData))
|
|
}
|