From 05b1431dfc48e84be00ef5f75bb2def53e51ea03 Mon Sep 17 00:00:00 2001 From: Ade Hery Shopyan Date: Thu, 5 Sep 2024 11:15:26 +0700 Subject: [PATCH] feat: initial commit --- .github/.DS_Store | Bin 0 -> 6148 bytes .github/CODEOWNERS | 1 + .github/pull_request_template.md | 20 + .github/workflows/ci.yaml | 39 ++ .github/workflows/publish.yaml | 40 ++ .github/workflows/release-please.yaml | 16 + .gitignore | 1 + Cargo.lock | 583 ++++++++++++++++++++++++++ Cargo.toml | 24 ++ LICENSE | 21 + README.md | 31 ++ src/lib.rs | 56 +++ 12 files changed, 832 insertions(+) create mode 100644 .github/.DS_Store create mode 100644 .github/CODEOWNERS create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/publish.yaml create mode 100644 .github/workflows/release-please.yaml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/lib.rs diff --git a/.github/.DS_Store b/.github/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2fadcfff0a9004bd4d240feea3125d92909da648 GIT binary patch literal 6148 zcmeHKJx{|h5Pb(73M?JFAo&+m;vYmM9ayMD2S%W@ECdB;E7t7%7=9wWyEBM}EG(!( zcaiQs`T5RW& z<5s={yr5>Ld)zUu=4jQ5cx^@KDnf#RU?3O>27-a#Gr%)jrGMlYeJ~IV1Os0T=>Cw{ z6pM_Fqir4RtOOwTIBh~*uge;fG8P#dM_MT2p+parTw;iab3SFiB4gv|;gDQ>NPhEY z@gnwi=1=AhDIB8@27-ZY2DJ924D|e;@R#W<^35f>U?3RyuM9}9oRwpKT|QfXe5anZ viS3$AMg1C8DAczu0UYQ)GBl&xlj`&"] +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +ring = { version = "0.17.8", features = ["wasm32_unknown_unknown_js"] } +biscuit = "0.7" +num-bigint = "0.4" +wasm-bindgen = "0.2" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +base64 = "0.13" +getrandom = { version = "0.2", features = ["js"] } + +[dev-dependencies] +wasm-bindgen-test = "0.3" + +[package.metadata.wasm-bindgen] +name = "jwe-wasm" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a4152f5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Kitabisa + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7cbda77 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +

+ + jwe-wasm + +

+ +

+ Library for encryption / decryption JWE using Biscuit +

+ +

+ Build Status + NPM Downloads + Latest Release + License +

+ +------ + +## Features + + * Written in [Rust](https://github.com/rust-lang/rust) + * Build with [Wasm-Pack](https://github.com/rustwasm/wasm-pack) + +## Getting Started + +Setup jwe-wasm with npm + +``` +$ npm install @kitabisa/jwe-wasm +``` diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..441f5b4 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,56 @@ +use wasm_bindgen::prelude::*; +use biscuit::Empty; +use biscuit::jwk::JWK; +use biscuit::jwe; +use biscuit::jwa::{EncryptionOptions, KeyManagementAlgorithm, ContentEncryptionAlgorithm}; +use num_bigint::BigUint; +use base64; +use serde_json; + +#[wasm_bindgen] +pub fn encrypt(payload: &str, key: &str) -> Result { + let jwk_key: JWK = serde_json::from_str(key).map_err(|e| e.to_string())?; + + let jwe = jwe::Compact::new_decrypted( + From::from(jwe::RegisteredHeader { + cek_algorithm: KeyManagementAlgorithm::A256GCMKW, + enc_algorithm: ContentEncryptionAlgorithm::A256GCM, + ..Default::default() + }), + payload.as_bytes().to_vec(), + ); + + let nonce_counter = BigUint::from_bytes_le(&vec![0; 96 / 8]); + assert!(nonce_counter.bits() <= 96); + let mut nonce_bytes = nonce_counter.to_bytes_le(); + nonce_bytes.resize(96 / 8, 0); + let options = EncryptionOptions::AES_GCM { nonce: nonce_bytes }; + + let encrypted_jwe = jwe.encrypt(&jwk_key, &options).map_err(|e| e.to_string())?; + let encrypted_jwe_str = serde_json::to_string(&encrypted_jwe).map_err(|e| e.to_string())?; + let encrypted_jwe_base64 = base64::encode(&encrypted_jwe_str); + + Ok(JsValue::from_str(&encrypted_jwe_base64)) +} + +#[wasm_bindgen] +pub fn decrypt(encrypted_jwe: &str, key: &str) -> Result { + let encrypted_jwe_str = base64::decode(encrypted_jwe).map_err(|e| e.to_string())?; + let encrypted_jwe_json = String::from_utf8(encrypted_jwe_str).map_err(|e| e.to_string())?; + + let jwk_key: JWK = serde_json::from_str(key).map_err(|e| e.to_string())?; + let encrypted_jwe: jwe::Compact, Empty> = serde_json::from_str(&encrypted_jwe_json).map_err(|e| e.to_string())?; + + let decrypted_jwe = encrypted_jwe + .decrypt( + &jwk_key, + KeyManagementAlgorithm::A256GCMKW, + ContentEncryptionAlgorithm::A256GCM, + ) + .map_err(|e| e.to_string())?; + + let decrypted_payload: &Vec = decrypted_jwe.payload().unwrap(); + let decrypted_str = std::str::from_utf8(&*decrypted_payload).map_err(|e| e.to_string())?; + + Ok(decrypted_str.to_string()) +}