rust
1. 安装 Rust工具链
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
2. 安装wasm-pack
cargo install wasm-pack
3. cargo.toml可添加wasm-bindgen (方便web打印console)
crate-type = ["cdylib"]
path = "src/lib.rs" # 引用的文件
[dependencies]
wasm-bindgen = "0.2.83"
rand = "0.8.5"
base64 = "0.22.1"
rsa = "0.9.8"
blowfish = "0.8.0"
block-modes = "0.8.0"
getrandom = { version = "0.2", features = ["js"] }
web-sys = { version = "0.3", features = ["Window", "Document"] }
4. lib.rs
use base64::{Engine as _, engine::general_purpose};
use block_modes::block_padding::Pkcs7;
use block_modes::{BlockMode, Cbc};
use blowfish::Blowfish;
use rand::{Rng, distributions::Alphanumeric};
use rsa::pkcs8::DecodePrivateKey;
use rsa::pkcs8::DecodePublicKey;
use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
static PRIKEY: &str = "-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----";
...
-----END PUBLIC KEY-----";
static IV: &[u8; 8] = b"12345678";
type BlowfishCbc = Cbc<Blowfish, Pkcs7>;
fn main() {
let rng = rand::thread_rng();
let key_str: String = rng
.sample_iter(Alphanumeric)
.take(8)
.map(char::from)
.collect();
println!("origin key is: {key_str}");
let data = encrypt_content(String::from("hello world"));
println!("encrypt result is: {data}");
let ret2 = decrypt_content(data);
println!("result is: {}", ret2);
}
fn decrypt_content(body: String) -> String {
let data = general_purpose::STANDARD
.decode(body)
.expect("decode error");
let head = &data[..256];
let body = &data[256..];
let private_key = RsaPrivateKey::from_pkcs8_pem(PRIKEY).expect("decrypt key init error");
let key = private_key
.decrypt(Pkcs1v15Encrypt, head)
.expect("decrypt key error");
let rest = BlowfishCbc::new_from_slices(key.as_slice(), IV)
.expect("decrypt body init error")
.decrypt_vec(body)
.expect("decrypt body error");
String::from_utf8(rest).unwrap_or_else(|_e| String::from("bad data"))
}
fn encrypt_content(data: String) -> String {
let rng = rand::thread_rng();
let key: String = rng
.sample_iter(Alphanumeric)
.take(8)
.map(char::from)
.collect();
let public_key = RsaPublicKey::from_public_key_pem(PUBKEY).expect("encrypt key init error");
let mut rng = rand::thread_rng();
//加密的header
let mut body = public_key
.encrypt(&mut rng, Pkcs1v15Encrypt, key.as_bytes())
.expect("encrypt body init error");
//加密剩下的
let rest = BlowfishCbc::new_from_slices(key.as_bytes(), IV)
.expect("encrypt body error")
.encrypt_vec(data.as_bytes());
body.extend(rest);
general_purpose::STANDARD.encode(body)
}
vue3+vite版本
1. 安装支持wasm插件
yarn add vite-plugin-wasm vite-plugin-top-level-await
2. 配置vite.config.ts
import wasm from 'vite-plugin-wasm'
import topLevelAwait from 'vite-plugin-top-level-await'
// 添加插件
plugins: [vue(), wasm(), topLevelAwait()]
3. 安装依赖
将打包后的pkg文件移入vue项目中,完成之后,我们可以在node_modules里面关联一下vue项目下面的pkg包。
yarn add pkg路径
若想自动编译同步更新node_modules里面内容,我们在package.json里面写一个执行命令。
"scripts": { "wasm": yarn add pkg路径" },
4. 封装 Wasm 工具类
import init, { encrypt_content, decrypt_content } from '../../pkg/bism';
// 初始化
(async function loadAndRunGoWasm() {
await init();
})();
export function encrypt(data: string) {
return encrypt_content(data);
}
export function decrypt(data: string) {
return decrypt_content(data);
}
import { encrypt, decrypt } from './wasmHelper';
const params = encrypt(JSON.stringify(加密参数));
console.log(`加密, ${params}`);
const result = decrypt(params);
console.log(`解密, ${result}`);