Skip to content

Commit

Permalink
feat: mv jwe as crypto
Browse files Browse the repository at this point in the history
  • Loading branch information
morlay committed Jun 6, 2024
1 parent 39eab46 commit 533fe50
Show file tree
Hide file tree
Showing 21 changed files with 237 additions and 187 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ bootstrap: build.monobundle
$(BUNX) monobundle

build.monobundle:
$(BUNX) turbo run build --filter=monobundle --force
$(BUNX) turbo run build --filter="@innoai-tech/monobundle" --force
$(BUN) install

lint:
$(BUNX) turbo run lint --filter=monobundle --force
$(BUNX) turbo run lint --filter="@innoai-tech/monobundle" --force

test:
$(BUN) test

build:
$(BUNX) turbo run build --filter=!monobundle --force
$(BUNX) turbo run build --filter="!@innoai-tech/monobundle" --force --concurrency=1

ci: bootstrap build test

Expand Down
Binary file modified bun.lockb
Binary file not shown.
6 changes: 3 additions & 3 deletions nodedevpkg/monobundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
},
"dependencies": {
"@innoai-tech/lodash": "workspace:^",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-node-resolve": "^15.2.3",
"browserslist": "^4.23.0",
"chalk": "^5.3.0",
"esbuild": "^0.21.1",
"esbuild": "^0.21.4",
"globby": "^14.0.1",
"js-yaml": "^4.1.0",
"minimatch": "^9.0.4",
"rollup": "^4.17.2",
"rollup": "^4.18.0",
"yargs": "^17.7.2"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion nodedevpkg/monobundle/src/pm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const projectManagers: { [name: string]: ProjectManager } = {
defaults: () => {
return {
scripts: {
build: "bunx --bun monobundle",
build: "bunx --bun @innoai-tech/monobundle",
lint: "bunx --bun prettier --write . ",
},
};
Expand Down
4 changes: 2 additions & 2 deletions nodedevpkg/purebundle/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion nodedevpkg/purebundle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ lto = true

[dependencies]
serde = { version = "1", features = ["derive"] }
swc_core = { version = "0.92.2", features = ["ecma_plugin_transform", "__parser"] }
swc_core = { version = "0.92.11", features = ["ecma_plugin_transform", "__parser"] }
swc_ecma_utils = { version = "0" }

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion nodedevpkg/purebundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@innoai-tech/purebundle",
"version": "0.3.1",
"dependencies": {
"@swc/core": "^1.5.5"
"@swc/core": "^1.5.25"
},
"exports": {
".": {
Expand Down
4 changes: 2 additions & 2 deletions nodepkg/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"dependencies": {
"@innoai-tech/lodash": "workspace:^",
"esbuild": "^0.21.1"
"esbuild": "^0.21.4"
},
"peerDependencies": {},
"browserslist": [
Expand Down Expand Up @@ -51,7 +51,7 @@
"directory": "nodepkg/config"
},
"scripts": {
"build": "bunx --bun monobundle",
"build": "bunx --bun @innoai-tech/monobundle",
"prepublishOnly": "bun run build",
"lint": "bunx --bun prettier --write . "
},
Expand Down
File renamed without changes.
5 changes: 3 additions & 2 deletions nodepkg/jwe/Cargo.toml → nodepkg/crypto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "jwe"
name = "crypto"
version = "0.1.0"
edition = "2021"

Expand All @@ -12,7 +12,8 @@ base64ct = { version = "1.6.0", features = ["alloc"] }
rand = "0.8"
sha1 = "0.10.6"
serde_json = "1"
aes-gcm = { version = "0.10", features = ["heapless", "getrandom"] }
aes = { version = "0.8.4" }
cfb-mode = { version = "0.8.2" }
serde = { version = "1.0", features = ["derive"] }
getrandom = { version = "*", features = ["js"] }
rsa = "0.9.6"
Expand Down
4 changes: 2 additions & 2 deletions nodepkg/jwe/README.md → nodepkg/crypto/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## jose
## crypto

[https://github.com/panva/jose] 基于 [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
被浏览器厂商强制实现为 https required.

在非 https 的环境,求助于 rust/wasm 来实现 jwe
在非 https 的环境,求助于 rust/wasm 来实现 crypto
18 changes: 18 additions & 0 deletions nodepkg/crypto/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface JWK {
kid: string;
kty: string;
n: string;
e: string;
alg: string;
use?: string;

[k: string]: any;
}

export function generate_aes_256_key(): Promise<string>

export function aes_256_cfb_decrypt(payload: Uint8Array, key: string): Promise<Uint8Array>

export function aes_256_cfb_encrypt(payload: Uint8Array, key: string): Promise<Uint8Array>

export function rsa_oaep_encrypt(payload: Uint8Array, key: JWK): Promise<string>
25 changes: 25 additions & 0 deletions nodepkg/crypto/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import init, {
rsa_oaep_encrypt as _rsa_oaep_encrypt,
generate_aes_256_key as _generate_aes_256_key,
aes_256_cfb_decrypt as _aes_256_cfb_decrypt,
aes_256_cfb_encrypt as _aes_256_cfb_encrypt
} from "./pkg/crypto";

// make vite happy
import wasmURL from "./pkg/crypto_bg.wasm?url";

export const generate_aes_256_key = () => {
return init(wasmURL).then(() => _generate_aes_256_key());
};

export const aes_256_cfb_decrypt = (payload, key) => {
return init(wasmURL).then(() => _aes_256_cfb_decrypt(payload, key));
};

export const aes_256_cfb_encrypt = (payload, key) => {
return init(wasmURL).then(() => _aes_256_cfb_encrypt(payload, key));
};

export const rsa_oaep_encrypt = (payload, key) => {
return init(wasmURL).then(() => _rsa_oaep_encrypt(payload, JSON.stringify(key)));
};
14 changes: 7 additions & 7 deletions nodepkg/jwe/package.json → nodepkg/crypto/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@innoai-tech/jwe",
"version": "0.2.2",
"name": "@innoai-tech/crypto",
"version": "0.1.0",
"exports": {
".": {
"import": {
Expand All @@ -10,20 +10,20 @@
}
},
"files": [
"pkg/jwe.d.ts",
"pkg/jwe.js",
"pkg/jwe_bg.wasm",
"pkg/crypto.d.ts",
"pkg/crypto.js",
"pkg/crypto_bg.wasm",
"index.d.ts",
"index.mjs"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "ssh://[email protected]:innoai-tech/nodekit.git",
"directory": "nodepkg/jwe"
"directory": "nodepkg/crypto"
},
"scripts": {
"test": "cargo test -- --nocapture",
"test:rust": "cargo test -- --nocapture",
"build": "bunx wasm-pack build --release --target web --no-pack",
"prepublishOnly": "bun run build"
},
Expand Down
134 changes: 134 additions & 0 deletions nodepkg/crypto/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use rsa::{
RsaPublicKey, BigUint, Oaep,
};
use rand::rngs::OsRng;
use sha1::Sha1;
use base64ct::{Encoding, Base64, Base64UrlUnpadded};
use aes::cipher::{
AsyncStreamCipher, KeyIvInit,
generic_array::GenericArray,
};


#[derive(Serialize, Deserialize)]
struct JWK {
alg: String,
kid: String,
kty: String,
n: String,
e: String,
}

#[wasm_bindgen]
pub fn rsa_oaep_encrypt(payload: &[u8], jwk_json: &str) -> String {
let jwk: JWK = serde_json::from_str(&jwk_json).unwrap();
let n = Base64UrlUnpadded::decode_vec(&jwk.n).unwrap();
let e = Base64::decode_vec(&jwk.e).unwrap();
let pub_key = RsaPublicKey::new(BigUint::from_bytes_be(&n), BigUint::from_bytes_be(&e)).unwrap();

// RSA-OAEP use Sha1
// RSA-OAEP-256 use Sha256
let encrypted_data = pub_key.encrypt(&mut OsRng, Oaep::new::<Sha1>(), payload).unwrap();
return Base64UrlUnpadded::encode_string(&encrypted_data);
}


#[derive(Serialize, Deserialize)]
struct Key {
enc: String,
key: String,
nonce: String,
}

type Aes256CfbEnc = cfb_mode::Encryptor<aes::Aes256>;

#[wasm_bindgen]
pub fn aes_256_cfb_encrypt(payload: &[u8], key_json: &str) -> Vec<u8> {
let k: Key = serde_json::from_str(&key_json).unwrap();
let key = Base64UrlUnpadded::decode_vec(&k.key).unwrap();
let iv = Base64UrlUnpadded::decode_vec(&k.nonce).unwrap();

let enc = Aes256CfbEnc::new(
&GenericArray::clone_from_slice(&key),
&GenericArray::clone_from_slice(&iv),
);

let mut ret = &mut payload.to_owned();
let _ = enc.encrypt(&mut ret);
return ret.to_vec();
}

type Aes256CfbDec = cfb_mode::Decryptor<aes::Aes256>;

#[wasm_bindgen]
pub fn aes_256_cfb_decrypt(payload: &[u8], key_json: &str) -> Vec<u8> {
let k: Key = serde_json::from_str(&key_json).unwrap();
let key = Base64UrlUnpadded::decode_vec(&k.key).unwrap();
let iv = Base64UrlUnpadded::decode_vec(&k.nonce).unwrap();

let dec = Aes256CfbDec::new(
&GenericArray::clone_from_slice(&key),
&GenericArray::clone_from_slice(&iv),
);

let mut ret = &mut payload.to_owned();
let _ = dec.decrypt_b2b(payload, &mut ret);
return ret.to_vec();
}

#[wasm_bindgen]
pub fn generate_aes_256_key() -> String {
let key: [u8; 32] = rand::random();
let nonce: [u8; 16] = rand::random();

let protected = Key {
enc: "AES-256-CFB".to_string(),
key: Base64UrlUnpadded::encode_string(&key),
nonce: Base64UrlUnpadded::encode_string(&nonce),
};

return serde_json::to_string(&protected).unwrap();
}


#[cfg(test)]
mod tests {
use super::*;

#[test]
fn should_do_rsa_oaep_encrypt() {
let payload = "{}";
let key = r#"
{
"alg": "RSA-OAEP",
"e": "AQAB",
"kid": "jSaViAqt/oc",
"kty": "RSA",
"n": "wv42EvfPu3KMzc9fVNJpQnlHmov9VMK96BcAYmgudYvCwYcHyINhglp-4L-vgoxQFFzLz6tmqk6BdsBz_Q9oXurtGGARk7mrl2xS45l2dUKJzaz2E7-VzRQzE5JbEDYrtnh-Qt0ETElfdzc9mCLw6rrVYyM6AZEhhb62ylgS7z6EMxX_xhVoa0mij2MFzW1dHKLDfCuUwd5drDYheF_i7FcFyT41Gc3qEk-1EubTVsxbdyrPRmLt9oCvLx7JbOoLivyv8q13LQkuTUOCqPoYJCdkhSXrKQTi30UkCTJCul9qvyJvUcql3pqb9w-LD4IxhC4OYwt1TuO_SedUdRD8Cw",
"use": "enc"
}
"#;

println!("{}", rsa_oaep_encrypt(payload.as_bytes(), key))
}

#[test]
fn should_do_generate_aes_256_key() {
println!("{}", generate_aes_256_key())
}

#[test]
fn should_do_aes_256_cfb_encrypt_and_decrypt() {
let plaintext = "1234567890";
let key = generate_aes_256_key();

let encrypted = aes_256_cfb_encrypt(plaintext.as_bytes(), &key);
println!("{:?}", encrypted);

let decrypted = aes_256_cfb_decrypt(encrypted.as_slice(), &key);
println!("{:?}", decrypted);
}
}

2 changes: 1 addition & 1 deletion nodepkg/fetcher/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"directory": "nodepkg/fetcher"
},
"scripts": {
"build": "bunx --bun monobundle",
"build": "bunx --bun @innoai-tech/monobundle",
"prepublishOnly": "bun run build",
"lint": "bunx --bun prettier --write . "
},
Expand Down
12 changes: 0 additions & 12 deletions nodepkg/jwe/index.d.ts

This file was deleted.

8 changes: 0 additions & 8 deletions nodepkg/jwe/index.mjs

This file was deleted.

Loading

0 comments on commit 533fe50

Please sign in to comment.