├── .github └── workflows │ └── rust.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── crypto ├── Cargo.toml └── src │ ├── crypto │ ├── crypto.rs │ ├── crypto_export.rs │ └── mod.rs │ ├── crypto_searchable │ ├── crypto_searchable_export.rs │ └── mod.rs │ ├── crypto_sortable │ ├── crypto_sortable_export.rs │ └── mod.rs │ ├── entities │ ├── group.rs │ ├── mod.rs │ └── user.rs │ ├── error │ └── mod.rs │ ├── file │ ├── file.rs │ ├── file_export.rs │ └── mod.rs │ ├── group │ ├── group.rs │ ├── group_export.rs │ ├── group_rank_check.rs │ └── mod.rs │ ├── keys │ ├── fips.rs │ ├── mod.rs │ ├── rec.rs │ └── std.rs │ ├── lib.rs │ ├── user │ ├── mod.rs │ ├── user.rs │ └── user_export.rs │ ├── util │ ├── mod.rs │ ├── public.rs │ ├── server.rs │ └── util_non_rust.rs │ └── util_req_full │ ├── file │ ├── file_export.rs │ └── mod.rs │ ├── group │ ├── group_export.rs │ └── mod.rs │ ├── mod.rs │ └── user │ ├── mod.rs │ └── user_export.rs ├── crypto_core ├── Cargo.toml └── src │ ├── cryptomat.rs │ ├── error.rs │ ├── group.rs │ ├── lib.rs │ └── user.rs ├── crypto_keys ├── crypto_fips_keys │ ├── Cargo.toml │ ├── src │ │ ├── core │ │ │ ├── asym.rs │ │ │ ├── hmac.rs │ │ │ ├── mod.rs │ │ │ ├── pw_hash.rs │ │ │ ├── sign.rs │ │ │ ├── sortable.rs │ │ │ └── sym.rs │ │ ├── lib.rs │ │ └── util │ │ │ ├── crypto │ │ │ ├── asym.rs │ │ │ ├── mod.rs │ │ │ ├── searchable.rs │ │ │ ├── sign.rs │ │ │ └── symmetric_key.rs │ │ │ ├── export.rs │ │ │ └── mod.rs │ └── tests │ │ ├── core_group.rs │ │ └── core_user.rs ├── crypto_rec_keys │ ├── Cargo.toml │ ├── src │ │ ├── core │ │ │ ├── asym │ │ │ │ ├── ecies.rs │ │ │ │ ├── ecies_ml_kem_hybrid.rs │ │ │ │ ├── mod.rs │ │ │ │ └── pqc_ml_kem.rs │ │ │ ├── mod.rs │ │ │ ├── pw_hash.rs │ │ │ ├── sign │ │ │ │ ├── ed25519_ml_dsa_hybrid.rs │ │ │ │ ├── mod.rs │ │ │ │ └── pqc_ml_dsa.rs │ │ │ └── sortable.rs │ │ ├── lib.rs │ │ └── util │ │ │ ├── crypto │ │ │ ├── asym.rs │ │ │ ├── mod.rs │ │ │ ├── sign.rs │ │ │ ├── sortable.rs │ │ │ └── symmetric_key.rs │ │ │ ├── export.rs │ │ │ └── mod.rs │ └── tests │ │ ├── core_group.rs │ │ └── core_user.rs └── crypto_std_keys │ ├── Cargo.toml │ ├── src │ ├── core │ │ ├── asym │ │ │ ├── ecies.rs │ │ │ ├── ecies_kyber_hybrid.rs │ │ │ ├── mod.rs │ │ │ └── pqc_kyber.rs │ │ ├── hmac │ │ │ ├── hmac_sha256.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── pw_hash │ │ │ ├── argon2.rs │ │ │ └── mod.rs │ │ ├── sign │ │ │ ├── ed25519.rs │ │ │ ├── ed25519_dilithium_hybrid.rs │ │ │ ├── mod.rs │ │ │ └── pqc_dilithium.rs │ │ ├── sortable │ │ │ ├── mod.rs │ │ │ └── ope.rs │ │ └── sym │ │ │ ├── aes_gcm.rs │ │ │ └── mod.rs │ ├── lib.rs │ └── util │ │ ├── crypto │ │ ├── asym.rs │ │ ├── mod.rs │ │ ├── searchable.rs │ │ ├── sign.rs │ │ ├── sortable.rs │ │ └── symmetric_key.rs │ │ ├── export.rs │ │ └── mod.rs │ └── tests │ ├── core_group.rs │ └── core_user.rs ├── crypto_light ├── Cargo.toml └── src │ ├── error.rs │ ├── group.rs │ ├── lib.rs │ ├── user │ ├── mod.rs │ ├── user.rs │ └── user_rust.rs │ └── util_req_full │ ├── group │ ├── mod.rs │ ├── non_rust.rs │ └── rust.rs │ ├── mod.rs │ └── user │ ├── mod.rs │ ├── non_rust.rs │ └── rust.rs ├── crypto_utils ├── Cargo.toml └── src │ ├── cryptomat │ ├── crypto.rs │ ├── macros.rs │ └── mod.rs │ ├── error.rs │ ├── full │ ├── mod.rs │ └── user.rs │ ├── group.rs │ ├── http │ ├── http_reqwest.rs │ ├── http_wasm.rs │ └── mod.rs │ ├── jwt.rs │ ├── lib.rs │ └── user.rs ├── implementation ├── dart │ ├── sentc_flutter_rust │ │ ├── Cargo.toml │ │ ├── flutter_rust_bridge.yaml │ │ ├── scripts │ │ │ ├── build-android.sh │ │ │ ├── build-apple.sh │ │ │ ├── build-other.sh │ │ │ └── generate_code.sh │ │ └── src │ │ │ ├── api │ │ │ ├── crypto.rs │ │ │ ├── file.rs │ │ │ ├── group.rs │ │ │ ├── mod.rs │ │ │ └── user.rs │ │ │ ├── frb_generated.rs │ │ │ └── lib.rs │ └── sentc_flutter_rust_light │ │ ├── Cargo.toml │ │ ├── flutter_rust_bridge.yaml │ │ ├── scripts │ │ ├── build-android.sh │ │ ├── build-apple.sh │ │ ├── build-other.sh │ │ └── generate_code.sh │ │ └── src │ │ ├── api │ │ ├── group.rs │ │ ├── mod.rs │ │ └── user.rs │ │ ├── frb_generated.rs │ │ └── lib.rs ├── js │ ├── sentc_wasm │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── babel.config.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── pkg │ │ │ ├── .gitignore │ │ │ └── package.json │ │ └── src │ │ │ ├── crypto.rs │ │ │ ├── file.rs │ │ │ ├── group.rs │ │ │ ├── lib.rs │ │ │ ├── user.rs │ │ │ └── util.rs │ └── sentc_wasm_light │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── babel.config.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── pkg │ │ ├── .gitignore │ │ └── package.json │ │ └── src │ │ ├── group.rs │ │ ├── lib.rs │ │ ├── user.rs │ │ └── util.rs └── nodejs │ └── sentc_node_js_rust │ ├── .cargo │ └── config.toml │ ├── .gitignore │ ├── .npmignore │ ├── .yarnrc.yml │ ├── Cargo.toml │ ├── LICENSE │ ├── build.rs │ ├── build.sh │ ├── index.d.ts │ ├── index.js │ ├── npm │ ├── darwin-arm64 │ │ ├── LICENSE │ │ ├── README.md │ │ └── package.json │ ├── darwin-x64 │ │ ├── LICENSE │ │ ├── README.md │ │ └── package.json │ ├── linux-arm64-gnu │ │ ├── LICENSE │ │ ├── README.md │ │ └── package.json │ ├── linux-arm64-musl │ │ ├── LICENSE │ │ ├── README.md │ │ └── package.json │ ├── linux-x64-gnu │ │ ├── LICENSE │ │ ├── README.md │ │ └── package.json │ └── win32-x64-msvc │ │ ├── LICENSE │ │ ├── README.md │ │ └── package.json │ ├── package.json │ ├── src │ ├── crypto.rs │ ├── file.rs │ ├── group.rs │ ├── lib.rs │ └── user.rs │ └── yarn.lock └── rustfmt.toml /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | std-keys-test: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - uses: actions/cache@v3 19 | with: 20 | path: | 21 | ~/.cargo/bin/ 22 | ~/.cargo/registry/index/ 23 | ~/.cargo/registry/cache/ 24 | ~/.cargo/git/db/ 25 | target/ 26 | key: ${{ runner.os }}-cargo-core-${{ hashFiles('**/Cargo.lock') }} 27 | 28 | - name: Std keys tests 29 | run: cargo test --package sentc-crypto-std-keys test --features=full 30 | 31 | crypto-default: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/checkout@v3 35 | 36 | - uses: actions/cache@v3 37 | with: 38 | path: | 39 | ~/.cargo/bin/ 40 | ~/.cargo/registry/index/ 41 | ~/.cargo/registry/cache/ 42 | ~/.cargo/git/db/ 43 | target/ 44 | key: ${{ runner.os }}-cargo-crypto_default-${{ hashFiles('**/Cargo.lock') }} 45 | 46 | - name: Crypto default tests 47 | run: cargo test --package sentc-crypto --lib test --features=server,export 48 | 49 | crypto-rust: 50 | runs-on: ubuntu-latest 51 | steps: 52 | - uses: actions/checkout@v3 53 | 54 | - uses: actions/cache@v3 55 | with: 56 | path: | 57 | ~/.cargo/bin/ 58 | ~/.cargo/registry/index/ 59 | ~/.cargo/registry/cache/ 60 | ~/.cargo/git/db/ 61 | target/ 62 | key: ${{ runner.os }}-cargo-crypto_rust-${{ hashFiles('**/Cargo.lock') }} 63 | 64 | - name: Crypto rust tests 65 | run: cargo test --package sentc-crypto --lib test --features=server,std_keys 66 | 67 | crypto-light-default: 68 | runs-on: ubuntu-latest 69 | steps: 70 | - uses: actions/checkout@v3 71 | 72 | - uses: actions/cache@v3 73 | with: 74 | path: | 75 | ~/.cargo/bin/ 76 | ~/.cargo/registry/index/ 77 | ~/.cargo/registry/cache/ 78 | ~/.cargo/git/db/ 79 | target/ 80 | key: ${{ runner.os }}-cargo-crypto_rust-${{ hashFiles('**/Cargo.lock') }} 81 | 82 | - name: Crypto light default tests 83 | run: cargo test --package sentc-crypto-light --lib test --features=export 84 | 85 | crypto-light-rust: 86 | runs-on: ubuntu-latest 87 | steps: 88 | - uses: actions/checkout@v3 89 | 90 | - uses: actions/cache@v3 91 | with: 92 | path: | 93 | ~/.cargo/bin/ 94 | ~/.cargo/registry/index/ 95 | ~/.cargo/registry/cache/ 96 | ~/.cargo/git/db/ 97 | target/ 98 | key: ${{ runner.os }}-cargo-crypto_rust-${{ hashFiles('**/Cargo.lock') }} 99 | 100 | - name: Crypto light rust tests 101 | run: cargo test --package sentc-crypto-light --lib test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .idea/ 3 | storage/ 4 | .run_config/ 5 | 6 | # local env files 7 | .env -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "implementation/js/sentc_js"] 2 | path = implementation/js/sentc_js 3 | url = https://github.com/sentclose/sentc-javascript.git 4 | [submodule "implementation/dart/sentc_flutter"] 5 | path = implementation/dart/sentc_flutter 6 | url = https://github.com/sentclose/sentc-flutter.git 7 | [submodule "implementation/nodejs/sentc-nodejs"] 8 | path = implementation/nodejs/sentc-nodejs 9 | url = https://github.com/sentclose/sentc-nodejs.git 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Sentc sdk changelog 2 | 3 | Changes also affect the [server API](https://github.com/sentclose/sentc-api). 4 | 5 | # 0.10.0 6 | 7 | - 2023/08/11 8 | - Added [Two-factor auth (2fa)](https://sentc.com/guide/e2ee/user.html#multi-factor-authentication) 9 | - Refactored [searchable](https://sentc.com/guide/e2ee/searchable.html) to use it without the api 10 | - [Verify login](https://sentc.com/protocol/#verify-login) (the password) before users receive the keys 11 | - Added [crypto light lib](https://sentc.com/guide/light/) with user and group management -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the sentc project 2 | 3 | Thank you for your interest to contribute to sentc. 4 | 5 | At the moment we are not accepting any pull requests but in the near future. 6 | 7 | ## Bugs 8 | 9 | If you found a bug please let us know and contact us via an issue or via email: contact@sentclose.com 10 | 11 | ## Feature requests 12 | 13 | For feature requests please contact us via email: contact@sentclose.com 14 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "crypto", 5 | "crypto_core", 6 | "crypto_utils", 7 | "crypto_light", 8 | "implementation/js/sentc_wasm", 9 | "implementation/js/sentc_wasm_light", 10 | "implementation/dart/sentc_flutter_rust", 11 | "implementation/dart/sentc_flutter_rust_light", 12 | "implementation/nodejs/sentc_node_js_rust", 13 | "crypto_keys/crypto_std_keys", 14 | "crypto_keys/crypto_fips_keys", 15 | "crypto_keys/crypto_rec_keys", 16 | ] 17 | 18 | [workspace.package] 19 | version = "0.15.0" 20 | edition = "2021" 21 | license-file = "LICENSE" 22 | authors = ["Sentclose ", "Jörn Heinemann "] 23 | homepage = "https://sentc.com/" 24 | documentation = "https://sentc.com/" 25 | repository = "https://github.com/sentclose/sentc" 26 | rust-version = "1.75.0" 27 | 28 | [workspace.dependencies] 29 | sentc-crypto-common = { version = "0.11.0", git = "https://github.com/sentclose/sentc-common.git", rev = "06cd7002a19d406807f9443ddfcd993bf9a46651" } 30 | #sentc-crypto-common = { path = "../backend/sentc-api/sdk-common" } # for local dev 31 | 32 | sentc-crypto-core = { version = "0.15.0", path = "crypto_core" } 33 | sentc-crypto-utils = { version = "0.15.0", path = "crypto_utils" } 34 | sentc-crypto = { version = "0.15.0", path = "crypto", default-features = false } 35 | sentc-crypto-light = { version = "0.15.0", path = "crypto_light", default-features = false } 36 | sentc-crypto-std-keys = { version = "0.15.0", path = "crypto_keys/crypto_std_keys" } 37 | sentc-crypto-fips-keys = { version = "0.15.0", path = "crypto_keys/crypto_fips_keys" } 38 | sentc-crypto-rec-keys = { version = "0.15.0", path = "crypto_keys/crypto_rec_keys" } 39 | 40 | #key export 41 | # must use this version because it is not comp. with password_hash from argon2 42 | base64ct = { version = "1.0.1", default-features = false, features = ["alloc"] } 43 | serde = { version = "1.0.137", features = ["derive"] } 44 | serde_json = { version = "1.0.81", default-features = false, features = ["alloc"] } 45 | 46 | [profile.dev] 47 | # Must always use panic = "abort" to avoid needing to define the unstable eh_personality lang item. 48 | panic = "abort" 49 | 50 | [profile.release] 51 | lto = true 52 | panic = "abort" 53 | strip = true 54 | 55 | [profile.release.package.sentc_wasm] 56 | opt-level = "z" 57 | overflow-checks = false 58 | debug = 0 59 | debug-assertions = false 60 | codegen-units = 1 61 | 62 | [profile.release.package.sentc_wasm_light] 63 | opt-level = "z" 64 | overflow-checks = false 65 | debug = 0 66 | debug-assertions = false 67 | codegen-units = 1 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sentc 2 | 3 | from Sentclose 4 | 5 | An end-to-end encryption sdk for developer with user management. 6 | 7 | Available in: 8 | 9 | - Javascript for the web 10 | - Dart with flutter 11 | - Rust 12 | 13 | ## Contains 14 | 15 | - User management: Register, login, authentication, authorisation 16 | - Group management: Invite or add member, role management, group encryption 17 | - Handling large files in browser and native 18 | 19 | ## Build from source 20 | 21 | #### Requirements: 22 | 23 | - Rust MRV 1.75.0 24 | - For flutter: 25 | - flutter_rust_bridge_codegen (`cargo install flutter_rust_bridge_codegen`) 26 | - cargo-ndk 27 | - llvm 28 | - flutter ffi (`dart pub global activate ffigen`) 29 | - For Javascript: 30 | - wasm-pack 31 | - node js min. version 14 lts 32 | 33 | ### Build for rust 34 | 35 | Build rust in the current workspace. 36 | 37 | ````shell 38 | cargo build --release 39 | ```` 40 | 41 | ### Build javascript (wasm) 42 | 43 | 1. Build with wasm pack in `implementation/js/sentc_wasm` 44 | 45 | ````shell 46 | cd ./implementation/js/sentc_wasm 47 | ```` 48 | 49 | ````shell 50 | wasm-pack build --target web 51 | ```` 52 | 53 | 2. Build typescript code in `implementation/js/sentc_wasm` 54 | 55 | ````shell 56 | cd ./implementation/js/sentc_wasm 57 | ```` 58 | 59 | ````shell 60 | npm run build 61 | ```` 62 | 63 | ### Build flutter 64 | 65 | Build with flutter rust bridge and cargo-ndk. 66 | 67 | 1. In the current workspace, generate the flutter code 68 | 69 | ````shell 70 | flutter_rust_bridge_codegen --rust-input implementation/dart/sentc_flutter_rust/src/sentc.rs --dart-output implementation/dart/sentc/lib/generated.dart --llvm-path 71 | ```` 72 | 73 | 2. build the android code with cargo-ndk in `implementation/dart/sentc_flutter_rust` 74 | 75 | ````shell 76 | cd ./implementation/dart/sentc_flutter_rust 77 | ```` 78 | 79 | ````shell 80 | cargo ndk -t armeabi-v7a -t arm64-v8a -t x86 -t x86_64 -o ../sentc/android/src/main/jniLibs build --release 81 | ```` -------------------------------------------------------------------------------- /crypto/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc-crypto" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | homepage.workspace = true 7 | authors.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | description = "The main implementation of the sentc sdk." 13 | 14 | include = [ 15 | "Cargo.toml", 16 | "../LICENSE", 17 | "src/**/*", 18 | ] 19 | 20 | [dependencies] 21 | sentc-crypto-core = { workspace = true } 22 | sentc-crypto-utils = { workspace = true, features = ["encryption"] } 23 | sentc-crypto-common = { workspace = true } 24 | sentc-crypto-std-keys = { workspace = true, features = ["full"], optional = true } 25 | sentc-crypto-fips-keys = { workspace = true, features = ["full"], optional = true } 26 | sentc-crypto-rec-keys = { workspace = true, features = ["full"], optional = true } 27 | 28 | # key and data export 29 | base64ct.workspace = true 30 | 31 | # json handling 32 | serde_json.workspace = true 33 | serde.workspace = true 34 | 35 | [features] 36 | export = ["std_keys"] 37 | std_keys = ["sentc-crypto-std-keys"] 38 | 39 | fips_keys = ["sentc-crypto-fips-keys"] 40 | 41 | rec_keys = ["sentc-crypto-rec-keys"] 42 | 43 | server = [] 44 | server_test = [] 45 | 46 | full_rustls = ["sentc-crypto-utils/crypto_full", "sentc-crypto-utils/rustls"] 47 | full_wasm = ["sentc-crypto-utils/crypto_full", "sentc-crypto-utils/wasm"] -------------------------------------------------------------------------------- /crypto/src/crypto/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod crypto; 2 | #[cfg(feature = "export")] 3 | mod crypto_export; 4 | 5 | pub use self::crypto::KeyGenerator; 6 | #[cfg(not(feature = "export"))] 7 | pub use self::crypto::*; 8 | #[cfg(feature = "export")] 9 | pub use self::crypto_export::*; 10 | #[cfg(feature = "export")] 11 | pub(crate) use self::crypto_export::{prepare_sign_key, prepare_verify_key}; 12 | -------------------------------------------------------------------------------- /crypto/src/crypto_searchable/crypto_searchable_export.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_common::content_searchable::SearchableCreateOutput; 5 | use sentc_crypto_std_keys::util::HmacKey; 6 | use sentc_crypto_utils::cryptomat::SearchableKeyWrapper; 7 | 8 | pub fn create_searchable_raw(key: &str, data: &str, full: bool, limit: Option) -> Result, String> 9 | { 10 | let key: HmacKey = key.parse()?; 11 | 12 | Ok(key.create_searchable_raw(data, full, limit)?) 13 | } 14 | 15 | pub fn create_searchable(key: &str, data: &str, full: bool, limit: Option) -> Result 16 | { 17 | let key: HmacKey = key.parse()?; 18 | 19 | Ok(key.create_searchable(data, full, limit)?) 20 | } 21 | 22 | pub fn search(key: &str, data: &str) -> Result 23 | { 24 | let key: HmacKey = key.parse()?; 25 | 26 | Ok(key.search(data)?) 27 | } 28 | 29 | #[cfg(test)] 30 | mod test 31 | { 32 | use super::*; 33 | use crate::group::test_fn::create_group_export; 34 | use crate::user::test_fn::create_user_export; 35 | 36 | #[test] 37 | fn test_create_full_searchable_item() 38 | { 39 | //create a group and use the hmac key 40 | let user = create_user_export(); 41 | let (_, _, _, hmac_keys, _) = create_group_export(&user.user_keys[0]); 42 | 43 | let hmac_key = &hmac_keys[0]; 44 | 45 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 46 | 47 | let string = create_searchable(hmac_key, text, true, None).unwrap(); 48 | 49 | //should be only one -> the full hash 50 | assert_eq!(string.hashes.len(), 1); 51 | } 52 | 53 | #[test] 54 | fn test_create_searchable_item() 55 | { 56 | //create a group and use the hmac key 57 | let user = create_user_export(); 58 | let (_, _, _, hmac_keys, _) = create_group_export(&user.user_keys[0]); 59 | 60 | let hmac_key = &hmac_keys[0]; 61 | 62 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 63 | 64 | let string = create_searchable(hmac_key, text, false, None).unwrap(); 65 | 66 | assert_eq!(string.hashes.len(), 39); 67 | } 68 | 69 | #[test] 70 | fn test_searchable_full_item() 71 | { 72 | //create a group and use the hmac key 73 | let user = create_user_export(); 74 | let (_, _, _, hmac_keys, _) = create_group_export(&user.user_keys[0]); 75 | 76 | let hmac_key = &hmac_keys[0]; 77 | 78 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 79 | 80 | let out = create_searchable(hmac_key, text, true, None).unwrap(); 81 | 82 | assert_eq!(out.hashes.len(), 1); 83 | 84 | //now get the output of the prepare search 85 | let search_str = search(hmac_key, "123").unwrap(); 86 | 87 | //should not contain only a part of the word because we used full 88 | assert!(!out.hashes.contains(&search_str)); 89 | 90 | //but should contain the full word 91 | let search_str = search(hmac_key, "123*+^êéèüöß@€&$ 👍 🚀 😎").unwrap(); 92 | 93 | assert!(out.hashes.contains(&search_str)); 94 | } 95 | 96 | #[test] 97 | fn test_searchable_item() 98 | { 99 | //create a group and use the hmac key 100 | let user = create_user_export(); 101 | let (_, _, _, hmac_keys, _) = create_group_export(&user.user_keys[0]); 102 | 103 | let hmac_key = &hmac_keys[0]; 104 | 105 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 106 | 107 | let out = create_searchable(hmac_key, text, false, None).unwrap(); 108 | 109 | assert_eq!(out.hashes.len(), 39); 110 | 111 | //now get the output of the prepare search 112 | let search_str = search(hmac_key, "123").unwrap(); 113 | 114 | assert!(out.hashes.contains(&search_str)); 115 | } 116 | 117 | #[test] 118 | fn test_not_create_same_output_with_different_hmac_keys() 119 | { 120 | let user = create_user_export(); 121 | let (_, _, _, hmac_keys, _) = create_group_export(&user.user_keys[0]); 122 | let hmac_key = &hmac_keys[0]; 123 | 124 | let (_, _, _, hmac_keys2, _) = create_group_export(&user.user_keys[0]); 125 | let hmac_key2 = &hmac_keys2[0]; 126 | 127 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 128 | 129 | let out = create_searchable(hmac_key, text, false, None).unwrap(); 130 | 131 | let search_str = search(hmac_key, "123").unwrap(); 132 | 133 | let search_str2 = search(hmac_key2, "123").unwrap(); 134 | 135 | assert_ne!(search_str, search_str2); 136 | 137 | assert!(out.hashes.contains(&search_str)); 138 | 139 | assert!(!out.hashes.contains(&search_str2)); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /crypto/src/crypto_searchable/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "export")] 2 | mod crypto_searchable_export; 3 | 4 | #[cfg(feature = "export")] 5 | pub use self::crypto_searchable_export::*; 6 | 7 | #[cfg(test)] 8 | mod test 9 | { 10 | use sentc_crypto_utils::cryptomat::SearchableKeyWrapper; 11 | 12 | use crate::group::test_fn::create_group; 13 | use crate::user::test_fn::create_user; 14 | 15 | #[test] 16 | fn test_create_full_searchable_item() 17 | { 18 | //create a group and use the hmac key 19 | let user = create_user(); 20 | let (_, _, _, hmac_keys, _) = create_group(&user.user_keys[0]); 21 | 22 | let hmac_key = &hmac_keys[0]; 23 | 24 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 25 | 26 | let out = hmac_key.create_searchable(text, true, None).unwrap(); 27 | 28 | //should be only one -> the full hash 29 | assert_eq!(out.hashes.len(), 1); 30 | } 31 | 32 | #[test] 33 | fn test_create_searchable_item() 34 | { 35 | //create a group and use the hmac key 36 | let user = create_user(); 37 | let (_, _, _, hmac_keys, _) = create_group(&user.user_keys[0]); 38 | 39 | let hmac_key = &hmac_keys[0]; 40 | 41 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 42 | 43 | let out = hmac_key.create_searchable(text, false, None).unwrap(); 44 | 45 | assert_eq!(out.hashes.len(), 39); 46 | } 47 | 48 | #[test] 49 | fn test_searchable_full_item() 50 | { 51 | //create a group and use the hmac key 52 | let user = create_user(); 53 | let (_, _, _, hmac_keys, _) = create_group(&user.user_keys[0]); 54 | 55 | let hmac_key = &hmac_keys[0]; 56 | 57 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 58 | 59 | let out = hmac_key.create_searchable(text, true, None).unwrap(); 60 | 61 | assert_eq!(out.hashes.len(), 1); 62 | 63 | //now get the output of the prepare search 64 | let search_str = hmac_key.search("123").unwrap(); 65 | 66 | //should not contain only a part of the word because we used full 67 | assert!(!out.hashes.contains(&search_str)); 68 | 69 | //but should contain the full word 70 | let search_str = hmac_key.search("123*+^êéèüöß@€&$ 👍 🚀 😎").unwrap(); 71 | 72 | assert!(out.hashes.contains(&search_str)); 73 | } 74 | 75 | #[test] 76 | fn test_searchable_item() 77 | { 78 | //create a group and use the hmac key 79 | let user = create_user(); 80 | let (_, _, _, hmac_keys, _) = create_group(&user.user_keys[0]); 81 | 82 | let hmac_key = &hmac_keys[0]; 83 | 84 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 85 | 86 | let out = hmac_key.create_searchable(text, false, None).unwrap(); 87 | 88 | assert_eq!(out.hashes.len(), 39); 89 | 90 | //now get the output of the prepare search 91 | let search_str = hmac_key.search("123").unwrap(); 92 | 93 | assert!(out.hashes.contains(&search_str)); 94 | } 95 | 96 | #[test] 97 | fn test_not_create_same_output_with_different_hmac_keys() 98 | { 99 | let user = create_user(); 100 | let (_, _, _, hmac_keys, _) = create_group(&user.user_keys[0]); 101 | let hmac_key = &hmac_keys[0]; 102 | 103 | let (_, _, _, hmac_keys2, _) = create_group(&user.user_keys[0]); 104 | let hmac_key2 = &hmac_keys2[0]; 105 | 106 | let text = "123*+^êéèüöß@€&$ 👍 🚀 😎"; 107 | 108 | let out = hmac_key.create_searchable(text, false, None).unwrap(); 109 | 110 | let search_str = hmac_key.search("123").unwrap(); 111 | 112 | let search_str2 = hmac_key2.search("123").unwrap(); 113 | 114 | assert_ne!(search_str, search_str2); 115 | 116 | assert!(out.hashes.contains(&search_str)); 117 | 118 | assert!(!out.hashes.contains(&search_str2)); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /crypto/src/crypto_sortable/crypto_sortable_export.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | 3 | use sentc_crypto_common::content_sortable::SortableEncryptOutput; 4 | use sentc_crypto_core::cryptomat::SortableKey as CoreSort; 5 | use sentc_crypto_std_keys::util::SortableKey; 6 | use sentc_crypto_utils::cryptomat::SortableKeyWrapper; 7 | 8 | use crate::SdkError; 9 | 10 | pub fn encrypt_raw_number(key: &str, data: u64) -> Result 11 | { 12 | let key: SortableKey = key.parse()?; 13 | Ok(key 14 | .get_key() 15 | .encrypt_sortable(data) 16 | .map_err(Into::::into)?) 17 | } 18 | 19 | pub fn encrypt_number(key: &str, data: u64) -> Result 20 | { 21 | let key: SortableKey = key.parse()?; 22 | Ok(key.encrypt_number(data)?) 23 | } 24 | 25 | pub fn encrypt_raw_string(key: &str, data: &str, max_len: Option) -> Result 26 | { 27 | let key: SortableKey = key.parse()?; 28 | Ok(key.encrypt_raw_string(data, max_len)?) 29 | } 30 | 31 | pub fn encrypt_string(key: &str, data: &str, max_len: Option) -> Result 32 | { 33 | let key: SortableKey = key.parse()?; 34 | Ok(key.encrypt_string(data, max_len)?) 35 | } 36 | 37 | #[cfg(test)] 38 | mod test 39 | { 40 | use super::*; 41 | use crate::group::test_fn::create_group_export; 42 | use crate::user::test_fn::create_user_export; 43 | 44 | extern crate std; 45 | 46 | #[test] 47 | fn test_simple() 48 | { 49 | let user = create_user_export(); 50 | let (_, _, _, _, sortable_keys) = create_group_export(&user.user_keys[0]); 51 | 52 | let key = &sortable_keys[0]; 53 | 54 | let values = ["a", "az", "azzz", "b", "ba", "baaa", "o", "oe", "z", "zaaa"]; 55 | 56 | let mut encrypted_vars = [0u64; 10]; 57 | 58 | for (i, value) in values.iter().enumerate() { 59 | encrypted_vars[i] = encrypt_raw_string(key, value, None).unwrap(); 60 | } 61 | 62 | //check 63 | let mut past_item = 0; 64 | 65 | for item in encrypted_vars { 66 | assert!(past_item < item); 67 | 68 | past_item = item; 69 | } 70 | } 71 | 72 | #[test] 73 | fn test_with_generated_key() 74 | { 75 | const KEY: &str = r#"{"Ope16":{"key":"5kGPKgLQKmuZeOWQyJ7vOg==","key_id":"1876b629-5795-471f-9704-0cac52eaf9a1"}}"#; 76 | 77 | let a = encrypt_raw_number(KEY, 262).unwrap(); 78 | let b = encrypt_raw_number(KEY, 263).unwrap(); 79 | let c = encrypt_raw_number(KEY, 65321).unwrap(); 80 | 81 | std::println!("a: {a}, b: {b}, c: {c}"); 82 | 83 | assert!(a < b); 84 | assert!(b < c); 85 | 86 | assert_eq!(a, 17455249); 87 | assert_eq!(b, 17488544); 88 | assert_eq!(c, 4280794268); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /crypto/src/crypto_sortable/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "export")] 2 | mod crypto_sortable_export; 3 | 4 | #[cfg(feature = "export")] 5 | pub use crypto_sortable_export::*; 6 | 7 | #[cfg(all(test, any(feature = "std_keys", feature = "rec_keys")))] 8 | mod test 9 | { 10 | use core::str::FromStr; 11 | 12 | use sentc_crypto_core::cryptomat::SortableKey as CoreSort; 13 | use sentc_crypto_utils::cryptomat::SortableKeyWrapper; 14 | 15 | use crate::group::test_fn::create_group; 16 | use crate::user::test_fn::create_user; 17 | 18 | extern crate std; 19 | 20 | #[cfg(feature = "std_keys")] 21 | pub type TestKey = sentc_crypto_std_keys::util::SortableKey; 22 | #[cfg(all(feature = "rec_keys", not(feature = "std_keys")))] 23 | pub type TestKey = sentc_crypto_rec_keys::util::SortableKey; 24 | 25 | #[test] 26 | fn test_simple() 27 | { 28 | let user = create_user(); 29 | let (_, _, _, _, sortable_keys) = create_group(&user.user_keys[0]); 30 | 31 | let key = &sortable_keys[0]; 32 | 33 | let values = ["a", "az", "azzz", "b", "ba", "baaa", "o", "oe", "z", "zaaa"]; 34 | 35 | let mut encrypted_vars = [0u64; 10]; 36 | 37 | for (i, value) in values.iter().enumerate() { 38 | encrypted_vars[i] = key.encrypt_raw_string(value, None).unwrap(); 39 | } 40 | 41 | //check 42 | let mut past_item = 0; 43 | 44 | for item in encrypted_vars { 45 | assert!(past_item < item); 46 | 47 | past_item = item; 48 | } 49 | } 50 | 51 | #[test] 52 | fn test_with_generated_key() 53 | { 54 | const KEY: &str = r#"{"Ope16":{"key":"5kGPKgLQKmuZeOWQyJ7vOg==","key_id":"1876b629-5795-471f-9704-0cac52eaf9a1"}}"#; 55 | 56 | let a = TestKey::from_str(KEY) 57 | .unwrap() 58 | .key 59 | .encrypt_sortable(262) 60 | .unwrap(); 61 | 62 | let b = TestKey::from_str(KEY) 63 | .unwrap() 64 | .key 65 | .encrypt_sortable(263) 66 | .unwrap(); 67 | 68 | let c = TestKey::from_str(KEY) 69 | .unwrap() 70 | .key 71 | .encrypt_sortable(65321) 72 | .unwrap(); 73 | 74 | std::println!("a: {a}, b: {b}, c: {c}"); 75 | 76 | assert!(a < b); 77 | assert!(b < c); 78 | 79 | assert_eq!(a, 17455249); 80 | assert_eq!(b, 17488544); 81 | assert_eq!(c, 4280794268); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /crypto/src/entities/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod group; 2 | pub mod user; 3 | -------------------------------------------------------------------------------- /crypto/src/error/mod.rs: -------------------------------------------------------------------------------- 1 | use alloc::format; 2 | use alloc::string::{String, ToString}; 3 | 4 | use sentc_crypto_core::Error; 5 | use sentc_crypto_utils::error::{out_error, SdkUtilError}; 6 | 7 | #[derive(Debug)] 8 | pub enum SdkError 9 | { 10 | Util(SdkUtilError), 11 | 12 | JsonToStringFailed, 13 | JsonParseFailed(serde_json::Error), 14 | JsonParse, 15 | 16 | DecodeHashedAuthKey, 17 | DecodeEncryptedDataFailed, 18 | DecodeSymKeyFailed, 19 | 20 | KeyDecryptFailed, 21 | 22 | LoginServerOutputWrong, 23 | KeyRotationServerOutputWrong, 24 | KeyRotationEncryptError(String), 25 | 26 | AlgNotFound, 27 | 28 | GroupRank, 29 | GroupUserKickRank, 30 | GroupPermission, 31 | } 32 | 33 | /** 34 | To convert the core error to sdk error 35 | */ 36 | impl From for SdkError 37 | { 38 | fn from(e: Error) -> Self 39 | { 40 | SdkError::Util(SdkUtilError::Base(e)) 41 | } 42 | } 43 | 44 | impl From for SdkError 45 | { 46 | fn from(value: SdkUtilError) -> Self 47 | { 48 | Self::Util(value) 49 | } 50 | } 51 | 52 | impl From for String 53 | { 54 | fn from(e: SdkError) -> Self 55 | { 56 | err_to_msg(e) 57 | } 58 | } 59 | 60 | impl From for SdkError 61 | { 62 | fn from(value: serde_json::Error) -> Self 63 | { 64 | Self::JsonParseFailed(value) 65 | } 66 | } 67 | 68 | pub fn err_to_msg(error: SdkError) -> String 69 | { 70 | match error { 71 | SdkError::Util(e) => sentc_crypto_utils::error::err_to_msg(e), 72 | 73 | SdkError::AlgNotFound => out_error("client_1", "The algorithms for this action was not found."), 74 | SdkError::JsonToStringFailed => out_error("client_100", "Cannot create a string from this object"), 75 | SdkError::JsonParse => out_error("client_102", "Cannot create an object from the input string"), 76 | SdkError::JsonParseFailed(err) => { 77 | format!("{{\"status\": {}, \"error_message\": \"{}\"}}", "client_101", err) 78 | }, 79 | 80 | SdkError::DecodeHashedAuthKey => out_error("client_6", "Can't decode the hashed authentication key"), 81 | SdkError::DecodeSymKeyFailed => { 82 | out_error( 83 | "client_9", 84 | "Can't decode the symmetric key. Maybe the format is wrong", 85 | ) 86 | }, 87 | SdkError::DecodeEncryptedDataFailed => out_error("client_10", "Can't decode the encrypted data"), 88 | 89 | SdkError::KeyDecryptFailed => out_error("client_21", "Can't decrypt a key. Maybe the format is wrong"), 90 | 91 | //Login error 92 | SdkError::LoginServerOutputWrong => { 93 | out_error( 94 | "client_130", 95 | "Error in login. Missing user keys. Maybe the Key creation was wrong", 96 | ) 97 | }, 98 | 99 | //group error 100 | SdkError::GroupRank => { 101 | out_error( 102 | "client_200", 103 | "No valid group rank. Please choose between 1 (highest) and 4 (lowest)", 104 | ) 105 | }, 106 | SdkError::GroupPermission => out_error("client_201", "No permission to fulfill this action"), 107 | SdkError::GroupUserKickRank => out_error("client_202", "The user to delete has a higher rank"), 108 | SdkError::KeyRotationServerOutputWrong => out_error("client_203", "The key rotation data is wrong and can't be decoded."), 109 | 110 | SdkError::KeyRotationEncryptError(e) => { 111 | out_error( 112 | "client_204", 113 | &("Key rotation failed for this account with this error message: ".to_string() + &e), 114 | ) 115 | }, 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /crypto/src/file/file_export.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_common::file::BelongsToType; 5 | use sentc_crypto_std_keys::util::SymmetricKey; 6 | 7 | use crate::crypto::{prepare_sign_key, prepare_verify_key}; 8 | use crate::keys::std::StdFileEncryptor; 9 | use crate::util::{export_core_sym_key_to_string, import_core_sym_key}; 10 | use crate::SdkError; 11 | 12 | pub fn prepare_register_file( 13 | master_key_id: String, 14 | key: &str, 15 | encrypted_content_key: String, 16 | belongs_to_id: Option, 17 | belongs_to_type: &str, 18 | file_name: Option, 19 | ) -> Result<(String, Option), String> 20 | { 21 | let belongs_to_type: BelongsToType = serde_json::from_str(belongs_to_type).map_err(SdkError::JsonParseFailed)?; 22 | 23 | let key: SymmetricKey = key.parse()?; 24 | 25 | let (server_input, encrypted_file_name) = super::file::prepare_register_file( 26 | master_key_id, 27 | &key, 28 | encrypted_content_key, 29 | belongs_to_id, 30 | belongs_to_type, 31 | file_name, 32 | )?; 33 | 34 | Ok((server_input, encrypted_file_name)) 35 | } 36 | 37 | pub fn done_register_file(server_output: &str) -> Result<(String, String), String> 38 | { 39 | Ok(super::file::done_register_file(server_output)?) 40 | } 41 | 42 | pub fn prepare_file_name_update(key: &str, file_name: Option) -> Result 43 | { 44 | let key: SymmetricKey = key.parse()?; 45 | Ok(super::file::prepare_file_name_update(&key, file_name)?) 46 | } 47 | 48 | pub fn encrypt_file_part_start(key: &str, part: &[u8], sign_key: Option<&str>) -> Result<(Vec, String), String> 49 | { 50 | let sign_key = prepare_sign_key(sign_key)?; 51 | let key: SymmetricKey = key.parse()?; 52 | 53 | let (encrypted_part, file_key) = StdFileEncryptor::encrypt_file_part_start(&key, part, sign_key.as_ref())?; 54 | 55 | let exported_file_key = export_core_sym_key_to_string(file_key)?; 56 | 57 | Ok((encrypted_part, exported_file_key)) 58 | } 59 | 60 | pub fn encrypt_file_part(pre_content_key: &str, part: &[u8], sign_key: Option<&str>) -> Result<(Vec, String), String> 61 | { 62 | let sign_key = prepare_sign_key(sign_key)?; 63 | let key = import_core_sym_key(pre_content_key)?; 64 | 65 | let (encrypted_part, file_key) = StdFileEncryptor::encrypt_file_part(&key, part, sign_key.as_ref())?; 66 | 67 | let exported_file_key = export_core_sym_key_to_string(file_key)?; 68 | 69 | Ok((encrypted_part, exported_file_key)) 70 | } 71 | 72 | pub fn decrypt_file_part_start(key: &str, part: &[u8], verify_key: Option<&str>) -> Result<(Vec, String), String> 73 | { 74 | let verify_key = prepare_verify_key(verify_key)?; 75 | let key: SymmetricKey = key.parse()?; 76 | 77 | let (decrypted, next_key) = StdFileEncryptor::decrypt_file_part_start(&key, part, verify_key.as_ref())?; 78 | 79 | let exported_file_key = export_core_sym_key_to_string(next_key)?; 80 | 81 | Ok((decrypted, exported_file_key)) 82 | } 83 | 84 | pub fn decrypt_file_part(pre_content_key: &str, part: &[u8], verify_key: Option<&str>) -> Result<(Vec, String), String> 85 | { 86 | let verify_key = prepare_verify_key(verify_key)?; 87 | let key = import_core_sym_key(pre_content_key)?; 88 | 89 | let (decrypted, next_key) = StdFileEncryptor::decrypt_file_part(&key, part, verify_key.as_ref())?; 90 | 91 | let exported_file_key = export_core_sym_key_to_string(next_key)?; 92 | 93 | Ok((decrypted, exported_file_key)) 94 | } 95 | -------------------------------------------------------------------------------- /crypto/src/file/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod file; 2 | #[cfg(feature = "export")] 3 | mod file_export; 4 | 5 | pub use self::file::FileEncryptor; 6 | #[cfg(not(feature = "export"))] 7 | pub use self::file::*; 8 | #[cfg(feature = "export")] 9 | pub use self::file_export::*; 10 | -------------------------------------------------------------------------------- /crypto/src/group/group_rank_check.rs: -------------------------------------------------------------------------------- 1 | use crate::SdkError; 2 | 3 | pub type VoidRes = Result<(), SdkError>; 4 | 5 | #[allow(clippy::needless_return_with_question_mark)] 6 | pub fn check_kick_user(user_rank: i32, admin_rank: i32) -> VoidRes 7 | { 8 | if admin_rank > 2 { 9 | return Err(SdkError::GroupPermission)?; 10 | } 11 | 12 | if admin_rank > user_rank { 13 | //user has a higher rank 14 | return Err(SdkError::GroupUserKickRank)?; 15 | } 16 | 17 | Ok(()) 18 | } 19 | 20 | #[allow(clippy::needless_return_with_question_mark)] 21 | pub fn check_group_delete(admin_rank: i32) -> VoidRes 22 | { 23 | if admin_rank > 1 { 24 | return Err(SdkError::GroupPermission)?; 25 | } 26 | 27 | Ok(()) 28 | } 29 | 30 | #[allow(clippy::needless_return_with_question_mark)] 31 | pub fn check_delete_user_rank(admin_rank: i32) -> VoidRes 32 | { 33 | if admin_rank > 2 { 34 | return Err(SdkError::GroupPermission)?; 35 | } 36 | 37 | Ok(()) 38 | } 39 | 40 | #[allow(clippy::needless_return_with_question_mark)] 41 | pub fn check_get_join_reqs(admin_rank: i32) -> VoidRes 42 | { 43 | if admin_rank > 2 { 44 | return Err(SdkError::GroupPermission)?; 45 | } 46 | 47 | Ok(()) 48 | } 49 | 50 | #[allow(clippy::needless_return_with_question_mark)] 51 | pub fn check_make_invite_req(admin_rank: i32) -> VoidRes 52 | { 53 | if admin_rank > 2 { 54 | return Err(SdkError::GroupPermission)?; 55 | } 56 | 57 | Ok(()) 58 | } 59 | 60 | #[allow(clippy::needless_return_with_question_mark)] 61 | pub fn check_create_sub_group(admin_rank: i32) -> VoidRes 62 | { 63 | if admin_rank > 1 { 64 | return Err(SdkError::GroupPermission)?; 65 | } 66 | 67 | Ok(()) 68 | } 69 | 70 | #[allow(clippy::needless_return_with_question_mark)] 71 | pub fn check_sent_join_req_list(admin_rank: i32) -> VoidRes 72 | { 73 | if admin_rank > 1 { 74 | return Err(SdkError::GroupPermission)?; 75 | } 76 | 77 | Ok(()) 78 | } 79 | -------------------------------------------------------------------------------- /crypto/src/keys/fips.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_fips_keys::core::pw_hash::PwHasherGetter; 2 | use sentc_crypto_fips_keys::core::sortable::NonSortableKeys; 3 | use sentc_crypto_fips_keys::core::sym::Aes256GcmKey; 4 | use sentc_crypto_fips_keys::util::{HmacKey, PublicKey, SecretKey, SignKey, SortableKey, SymmetricKey, VerifyKey}; 5 | 6 | use crate::crypto::KeyGenerator; 7 | use crate::entities::group::GroupKeyData; 8 | use crate::entities::user::{UserDataInt, UserKeyDataInt}; 9 | use crate::file::FileEncryptor; 10 | use crate::group::Group; 11 | use crate::user::User; 12 | 13 | pub type FipsGroup = Group< 14 | SymmetricKey, 15 | SecretKey, 16 | SignKey, 17 | sentc_crypto_fips_keys::core::hmac::HmacKey, 18 | NonSortableKeys, 19 | SymmetricKey, 20 | SecretKey, 21 | SignKey, 22 | HmacKey, 23 | SortableKey, 24 | PublicKey, 25 | VerifyKey, 26 | >; 27 | 28 | pub type FipsGroupKeyData = GroupKeyData; 29 | 30 | pub type FipsUser = User< 31 | SymmetricKey, 32 | SecretKey, 33 | SignKey, 34 | sentc_crypto_fips_keys::core::hmac::HmacKey, 35 | NonSortableKeys, 36 | SymmetricKey, 37 | SecretKey, 38 | SignKey, 39 | HmacKey, 40 | SortableKey, 41 | PublicKey, 42 | VerifyKey, 43 | PwHasherGetter, 44 | >; 45 | 46 | pub type FipsUserDataInt = UserDataInt; 47 | 48 | pub type FipsUserKeyDataInt = UserKeyDataInt; 49 | 50 | pub type FipsKeyGenerator = KeyGenerator; 51 | 52 | pub type FipsFileEncryptor = FileEncryptor; 53 | 54 | #[cfg(any(feature = "full_rustls", feature = "full_wasm"))] 55 | pub type FipsPreLoginOut = crate::util_req_full::user::PreLoginOut< 56 | SymmetricKey, 57 | SecretKey, 58 | PublicKey, 59 | SignKey, 60 | VerifyKey, 61 | sentc_crypto_fips_keys::core::pw_hash::DeriveAuthKeyForAuth, 62 | >; 63 | -------------------------------------------------------------------------------- /crypto/src/keys/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "fips_keys")] 2 | pub mod fips; 3 | #[cfg(feature = "rec_keys")] 4 | pub mod rec; 5 | #[cfg(feature = "std_keys")] 6 | pub mod std; 7 | -------------------------------------------------------------------------------- /crypto/src/keys/rec.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_rec_keys::core::pw_hash::PwHasher; 2 | use sentc_crypto_rec_keys::core::sym::Aes256GcmKey; 3 | use sentc_crypto_rec_keys::util::{HmacKey, PublicKey, SecretKey, SignKey, SortableKey, SymmetricKey, VerifyKey}; 4 | 5 | use crate::crypto::KeyGenerator; 6 | use crate::entities::group::GroupKeyData; 7 | use crate::entities::user::{UserDataInt, UserKeyDataInt}; 8 | use crate::file::FileEncryptor; 9 | use crate::group::Group; 10 | use crate::user::User; 11 | 12 | pub type RecGroup = Group< 13 | SymmetricKey, 14 | SecretKey, 15 | SignKey, 16 | sentc_crypto_rec_keys::core::hmac::HmacKey, 17 | sentc_crypto_rec_keys::core::sortable::OpeSortableKey, 18 | SymmetricKey, 19 | SecretKey, 20 | SignKey, 21 | HmacKey, 22 | SortableKey, 23 | PublicKey, 24 | VerifyKey, 25 | >; 26 | 27 | pub type RecGroupKeyData = GroupKeyData; 28 | 29 | pub type RecUser = User< 30 | SymmetricKey, 31 | SecretKey, 32 | SignKey, 33 | sentc_crypto_rec_keys::core::hmac::HmacKey, 34 | sentc_crypto_rec_keys::core::sortable::OpeSortableKey, 35 | SymmetricKey, 36 | SecretKey, 37 | SignKey, 38 | HmacKey, 39 | SortableKey, 40 | PublicKey, 41 | VerifyKey, 42 | PwHasher, 43 | >; 44 | 45 | pub type RecUserDataInt = UserDataInt; 46 | 47 | pub type RecUserKeyDataInt = UserKeyDataInt; 48 | 49 | pub type RecKeyGenerator = KeyGenerator; 50 | 51 | pub type RecFileEncryptor = FileEncryptor; 52 | 53 | #[cfg(any(feature = "full_rustls", feature = "full_wasm"))] 54 | pub type FipsPreLoginOut = crate::util_req_full::user::PreLoginOut< 55 | SymmetricKey, 56 | SecretKey, 57 | PublicKey, 58 | SignKey, 59 | VerifyKey, 60 | sentc_crypto_rec_keys::core::pw_hash::DeriveAuthKeyForAuth, 61 | >; 62 | -------------------------------------------------------------------------------- /crypto/src/keys/std.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_std_keys::core::PwHasherGetter; 2 | use sentc_crypto_std_keys::util::{HmacKey, PublicKey, SecretKey, SignKey, SortableKey, SymmetricKey, VerifyKey}; 3 | 4 | use crate::{crypto, entities, file, group, user}; 5 | 6 | pub type StdGroup = group::Group< 7 | SymmetricKey, 8 | SecretKey, 9 | SignKey, 10 | sentc_crypto_std_keys::core::HmacKey, 11 | sentc_crypto_std_keys::core::SortKeys, 12 | SymmetricKey, 13 | SecretKey, 14 | SignKey, 15 | HmacKey, 16 | SortableKey, 17 | PublicKey, 18 | VerifyKey, 19 | >; 20 | 21 | pub type StdGroupKeyData = entities::group::GroupKeyData; 22 | 23 | pub type StdUser = user::User< 24 | SymmetricKey, 25 | SecretKey, 26 | SignKey, 27 | sentc_crypto_std_keys::core::HmacKey, 28 | sentc_crypto_std_keys::core::SortKeys, 29 | SymmetricKey, 30 | SecretKey, 31 | SignKey, 32 | HmacKey, 33 | SortableKey, 34 | PublicKey, 35 | VerifyKey, 36 | PwHasherGetter, 37 | >; 38 | 39 | pub type StdUserDataInt = entities::user::UserDataInt; 40 | 41 | pub type StdUserKeyDataInt = entities::user::UserKeyDataInt; 42 | 43 | pub type StdKeyGenerator = crypto::KeyGenerator; 44 | 45 | pub type StdFileEncryptor = 46 | file::FileEncryptor; 47 | 48 | #[cfg(any(feature = "full_rustls", feature = "full_wasm"))] 49 | pub type StdPreLoginOut = crate::util_req_full::user::PreLoginOut< 50 | SymmetricKey, 51 | SecretKey, 52 | PublicKey, 53 | SignKey, 54 | VerifyKey, 55 | sentc_crypto_std_keys::core::DeriveMasterKeyForAuth, 56 | >; 57 | -------------------------------------------------------------------------------- /crypto/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![allow( 3 | clippy::module_inception, 4 | clippy::infallible_destructuring_match, 5 | clippy::tabs_in_doc_comments, 6 | clippy::manual_map, 7 | clippy::explicit_counter_loop, 8 | clippy::manual_range_contains, 9 | clippy::type_complexity 10 | )] 11 | 12 | //! The base lib for all sentc libraries. Containing user- and group management as well as encryption, file-handling and search- and sortable encryption 13 | //! 14 | //! These are very low-level functionalities. It is recommended to use it with a sdks. 15 | //! 16 | //! This lib is defined as a "template" to use it with different crypto implementations thanks to rusts generic. 17 | //! As long as the implementation follows the traits defined in sentc-crypto-core and sentc-crypto-utils crate it can be used with this lib. 18 | //! 19 | //! # Overview 20 | //! 21 | //! Users and groups are structs with generic parameter. 22 | //! Pre-defined users and groups can be found in the keys mod 23 | //! 24 | //! Online actions like creating a new user or group can be found in the util_req_full mod 25 | //! and is only available when activating the feature full_rustls or full_wasm. 26 | //! 27 | //! For sdk implementations that uses ffi or wasm, the export feature can be used. 28 | //! All Keys are returned as exported string in base64 and all errors are string as well. This makes it easy to integrate with wasm. 29 | //! In every mod there are an _export file with the export implementation of the actual mod. 30 | //! For a full rust implementation this is not recommended. 31 | //! 32 | //! Every function with prepare and done or finish prefix can be used "offline" without server interactions 33 | //! but required the server responses. This is useful when certain processes needs to be handled differently. 34 | //! 35 | //! # Get started 36 | //! 37 | //! ```toml 38 | //! sentc-crypto = "" 39 | //! ``` 40 | //! 41 | //! To install it with pre-defined crypto implementation: 42 | //! 43 | //! * For the std keys: 44 | //! ```toml 45 | //! sentc-crypto = { version = "", features = ["std_keys"] } 46 | //! ``` 47 | //! 48 | //! * For fips complaint keys: 49 | //! ```toml 50 | //! sentc-crypto = { version = "", features = ["fips_keys"] } 51 | //! ``` 52 | //! 53 | //! * For the recommended keys: 54 | //! ```toml 55 | //! sentc-crypto = { version = "", features = ["rec_keys"] } 56 | //! ``` 57 | //! 58 | //! To get the online actions add the feature: 59 | //! * full_rustls to use rustls 60 | //! * full_wasm to use the web assembly requests 61 | 62 | extern crate alloc; 63 | 64 | pub mod crypto; 65 | pub mod crypto_searchable; 66 | pub mod crypto_sortable; 67 | pub mod entities; 68 | mod error; 69 | pub mod file; 70 | pub mod group; 71 | pub mod user; 72 | pub mod util; 73 | 74 | pub mod keys; 75 | #[cfg(any(feature = "full_rustls", feature = "full_wasm"))] 76 | pub mod util_req_full; 77 | 78 | /** 79 | For server testing export every common 80 | because using common from path via submodule resolve in version conflicts when using it in tests 81 | */ 82 | #[cfg(feature = "server_test")] 83 | pub use sentc_crypto_common as sdk_common; 84 | /** 85 | Reexport of the crypto core crate to access the raw types 86 | */ 87 | pub use sentc_crypto_core as sdk_core; 88 | #[cfg(feature = "fips_keys")] 89 | pub use sentc_crypto_fips_keys as fips_keys; 90 | #[cfg(feature = "rec_keys")] 91 | pub use sentc_crypto_rec_keys as rec_keys; 92 | #[cfg(feature = "std_keys")] 93 | pub use sentc_crypto_std_keys as std_keys; 94 | pub use sentc_crypto_utils as sdk_utils; 95 | 96 | pub use self::error::{err_to_msg, SdkError}; 97 | -------------------------------------------------------------------------------- /crypto/src/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod public; 2 | #[cfg(feature = "server")] 3 | pub mod server; 4 | #[cfg(feature = "export")] 5 | mod util_non_rust; 6 | 7 | #[cfg(feature = "export")] 8 | pub(crate) use self::util_non_rust::{export_core_sym_key_to_string, import_core_sym_key}; 9 | -------------------------------------------------------------------------------- /crypto/src/util/public.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "export")] 2 | use alloc::string::String; 3 | use alloc::vec::Vec; 4 | 5 | use sentc_crypto_common::user::{UserPublicKeyData, UserPublicKeyDataServerOutput, UserVerifyKeyData, UserVerifyKeyDataServerOutput}; 6 | #[cfg(feature = "export")] 7 | use sentc_crypto_common::{EncryptionKeyPairId, SignKeyPairId}; 8 | use sentc_crypto_core::cryptomat::{ClientRandomValue, ClientRandomValueComposer}; 9 | use sentc_crypto_utils::client_random_value_from_string; 10 | use serde::Deserialize; 11 | 12 | use crate::error::SdkError; 13 | 14 | pub fn handle_server_response<'de, T: Deserialize<'de>>(res: &'de str) -> Result 15 | { 16 | Ok(sentc_crypto_utils::handle_server_response(res)?) 17 | } 18 | 19 | /** 20 | Getting the result of a simple server response. 21 | */ 22 | pub fn handle_general_server_response(res: &str) -> Result<(), SdkError> 23 | { 24 | Ok(sentc_crypto_utils::handle_general_server_response(res)?) 25 | } 26 | 27 | pub fn generate_salt_from_base64(client_random_value: &str, alg: &str, add_str: &str) -> Result, SdkError> 28 | { 29 | let client_random_value = client_random_value_from_string::(client_random_value, alg)?; 30 | 31 | Ok(client_random_value.generate_salt(add_str)) 32 | } 33 | 34 | pub fn import_public_key_from_string_into_format(public_key: &str) -> Result 35 | { 36 | let out: UserPublicKeyDataServerOutput = handle_server_response(public_key)?; 37 | 38 | let public_key = UserPublicKeyData { 39 | public_key_pem: out.public_key, 40 | public_key_alg: out.public_key_alg, 41 | public_key_id: out.public_key_id, 42 | public_key_sig: out.public_key_sig, 43 | public_key_sig_key_id: out.public_key_sig_key_id, 44 | }; 45 | 46 | Ok(public_key) 47 | } 48 | 49 | pub fn import_verify_key_from_string_into_format(verify_key: &str) -> Result 50 | { 51 | let out: UserVerifyKeyDataServerOutput = handle_server_response(verify_key)?; 52 | 53 | let verify_key = UserVerifyKeyData { 54 | verify_key_pem: out.verify_key, 55 | verify_key_alg: out.verify_key_alg, 56 | verify_key_id: out.verify_key_id, 57 | }; 58 | 59 | Ok(verify_key) 60 | } 61 | 62 | #[cfg(feature = "export")] 63 | pub fn import_public_key_from_string_into_export_string(public_key: &str) -> Result<(String, EncryptionKeyPairId, Option), String> 64 | { 65 | let public_key = import_public_key_from_string_into_format(public_key)?; 66 | 67 | Ok(( 68 | public_key 69 | .to_string() 70 | .map_err(|_| SdkError::JsonToStringFailed)?, 71 | public_key.public_key_id, 72 | public_key.public_key_sig_key_id, 73 | )) 74 | } 75 | 76 | #[cfg(feature = "export")] 77 | pub fn import_verify_key_from_string_into_export_string(verify_key: &str) -> Result<(String, SignKeyPairId), String> 78 | { 79 | let public_key = import_verify_key_from_string_into_format(verify_key)?; 80 | 81 | Ok(( 82 | public_key 83 | .to_string() 84 | .map_err(|_| SdkError::JsonToStringFailed)?, 85 | public_key.verify_key_id, 86 | )) 87 | } 88 | -------------------------------------------------------------------------------- /crypto/src/util/server.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use base64ct::{Base64, Encoding}; 5 | use sentc_crypto_core::cryptomat::{ClientRandomValueComposer, DeriveAuthKeyForAuth, DeriveAuthKeyForAuthComposer, Pk}; 6 | use sentc_crypto_utils::cryptomat::StaticKeyComposerWrapper; 7 | 8 | use crate::util::public::generate_salt_from_base64; 9 | use crate::SdkError; 10 | 11 | #[macro_export] 12 | macro_rules! traverse_keys { 13 | // Base case: No more types to try, return an error 14 | ($method:ident, ($($arg:expr),*), []) => { 15 | Err($crate::SdkError::AlgNotFound) 16 | }; 17 | // Recursive case: Try the first type, if it fails with AlgNotFound, try the next types 18 | ($method:ident, ($($arg:expr),*), [$first:ty $(, $rest:ty)*]) => { 19 | match $method::<$first>($($arg),*) { 20 | Ok(val) => Ok(val), 21 | Err(err) => match err { 22 | $crate::SdkError::Util($crate::sdk_utils::error::SdkUtilError::Base($crate::sdk_core::Error::AlgNotFound)) | 23 | $crate::SdkError::Util($crate::sdk_utils::error::SdkUtilError::AlgNotFound) | 24 | $crate::SdkError::AlgNotFound => traverse_keys!($method, ($($arg),*), [$($rest),*]), 25 | _ => Err(err), 26 | } 27 | } 28 | }; 29 | } 30 | 31 | /** 32 | # Generates a salt 33 | 34 | from a base64 encoded client random value 35 | 36 | returns the salt as base64 encoded 37 | */ 38 | pub fn generate_salt_from_base64_to_string( 39 | client_random_value: &str, 40 | alg: &str, 41 | add_str: &str, 42 | ) -> Result 43 | { 44 | let salt = generate_salt_from_base64::(client_random_value, alg, add_str)?; 45 | 46 | Ok(Base64::encode_string(&salt)) 47 | } 48 | 49 | pub fn get_auth_keys_from_base64(client_auth_key: &str, alg: &str) -> Result, SdkError> 50 | { 51 | let v_c = Base64::decode_vec(client_auth_key).map_err(|_| SdkError::DecodeHashedAuthKey)?; 52 | 53 | let client_auth_key = DAK::from_bytes(v_c, alg)?; 54 | 55 | //hash the client key 56 | 57 | Ok(client_auth_key.hash_auth_key()?) 58 | } 59 | 60 | /** 61 | Use it for the server hashed auth key (from register) and when the client auth key was hashed extern and sent to the server 62 | */ 63 | pub fn get_hashed_auth_key_from_string(hashed_auth_key: &str) -> Result, SdkError> 64 | { 65 | Base64::decode_vec(hashed_auth_key).map_err(|_| SdkError::DecodeHashedAuthKey) 66 | } 67 | 68 | pub fn encrypt_ephemeral_group_key_with_public_key( 69 | public_key_in_pem: &str, 70 | public_key_alg: &str, 71 | eph_key: &str, 72 | ) -> Result 73 | { 74 | let public_key = P::pk_inner_from_pem(public_key_in_pem, public_key_alg)?; 75 | 76 | let eph_key = Base64::decode_vec(eph_key).map_err(|_| SdkError::DecodeSymKeyFailed)?; 77 | 78 | let encrypted_eph_key = public_key.encrypt(&eph_key)?; 79 | 80 | Ok(Base64::encode_string(&encrypted_eph_key)) 81 | } 82 | 83 | pub fn encrypt_login_verify_challenge( 84 | public_key_in_pem: &str, 85 | public_key_alg: &str, 86 | challenge: &str, 87 | ) -> Result 88 | { 89 | let public_key = P::pk_inner_from_pem(public_key_in_pem, public_key_alg)?; 90 | 91 | let encrypted_eph_key = public_key.encrypt(challenge.as_bytes())?; 92 | 93 | Ok(Base64::encode_string(&encrypted_eph_key)) 94 | } 95 | -------------------------------------------------------------------------------- /crypto/src/util/util_non_rust.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | 3 | use base64ct::{Base64, Encoding}; 4 | use sentc_crypto_std_keys::core::SymmetricKey; 5 | use sentc_crypto_utils::error::SdkUtilError; 6 | use serde::{Deserialize, Serialize}; 7 | use serde_json::{from_str, to_string}; 8 | 9 | use crate::SdkError; 10 | 11 | #[derive(Serialize, Deserialize)] 12 | pub enum ExportedCoreSymKey 13 | { 14 | Aes 15 | { 16 | key: String 17 | }, 18 | } 19 | 20 | /** 21 | Export a core sym key. 22 | 23 | This is only used when this key is stored in the client and is never send to the server 24 | */ 25 | pub(crate) fn export_core_sym_key(key: SymmetricKey) -> ExportedCoreSymKey 26 | { 27 | match key { 28 | SymmetricKey::Aes(k) => { 29 | let sym_key = Base64::encode_string(k.as_ref()); 30 | 31 | ExportedCoreSymKey::Aes { 32 | key: sym_key, 33 | } 34 | }, 35 | } 36 | } 37 | 38 | pub(crate) fn export_core_sym_key_to_string(key: SymmetricKey) -> Result 39 | { 40 | let key = export_core_sym_key(key); 41 | 42 | to_string(&key).map_err(|_e| SdkError::JsonToStringFailed) 43 | } 44 | 45 | pub(crate) fn import_core_sym_key(key_string: &str) -> Result 46 | { 47 | let key_format = from_str(key_string).map_err(|_| SdkUtilError::ImportSymmetricKeyFailed)?; 48 | 49 | import_core_sym_key_from_format(&key_format) 50 | } 51 | 52 | pub(crate) fn import_core_sym_key_from_format(key: &ExportedCoreSymKey) -> Result 53 | { 54 | match key { 55 | ExportedCoreSymKey::Aes { 56 | key, 57 | } => { 58 | //to bytes via base64 59 | let bytes = Base64::decode_vec(key.as_str()).map_err(|_| SdkUtilError::ImportSymmetricKeyFailed)?; 60 | 61 | Ok(SymmetricKey::aes_key_from_bytes_owned(bytes)?) 62 | }, 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /crypto/src/util_req_full/file/file_export.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_std_keys::util::SymmetricKey; 5 | 6 | use crate::crypto::{prepare_sign_key, prepare_verify_key}; 7 | use crate::keys::std::StdFileEncryptor; 8 | use crate::util::{export_core_sym_key_to_string, import_core_sym_key}; 9 | 10 | pub async fn download_and_decrypt_file_part_start( 11 | base_url: String, 12 | url_prefix: Option, 13 | auth_token: &str, 14 | part_id: &str, 15 | content_key: &str, 16 | verify_key_data: Option<&str>, 17 | ) -> Result<(Vec, String), String> 18 | { 19 | let verify_key = prepare_verify_key(verify_key_data)?; 20 | let key: SymmetricKey = content_key.parse()?; 21 | 22 | let (decrypted, next_key) = 23 | StdFileEncryptor::download_and_decrypt_file_part_start(base_url, url_prefix, auth_token, part_id, &key, verify_key.as_ref()).await?; 24 | 25 | let exported_file_key = export_core_sym_key_to_string(next_key)?; 26 | 27 | Ok((decrypted, exported_file_key)) 28 | } 29 | 30 | pub async fn download_and_decrypt_file_part( 31 | base_url: String, 32 | url_prefix: Option, 33 | auth_token: &str, 34 | part_id: &str, 35 | pre_key: &str, 36 | verify_key_data: Option<&str>, 37 | ) -> Result<(Vec, String), String> 38 | { 39 | let verify_key = prepare_verify_key(verify_key_data)?; 40 | let key = import_core_sym_key(pre_key)?; 41 | 42 | let (decrypted, next_key) = 43 | StdFileEncryptor::download_and_decrypt_file_part(base_url, url_prefix, auth_token, part_id, &key, verify_key.as_ref()).await?; 44 | 45 | let exported_file_key = export_core_sym_key_to_string(next_key)?; 46 | 47 | Ok((decrypted, exported_file_key)) 48 | } 49 | 50 | //__________________________________________________________________________________________________ 51 | 52 | #[allow(clippy::too_many_arguments)] 53 | pub async fn upload_part_start( 54 | base_url: String, 55 | url_prefix: Option, 56 | auth_token: &str, 57 | jwt: &str, 58 | session_id: &str, 59 | end: bool, 60 | sequence: i32, 61 | content_key: &str, 62 | sign_key: Option<&str>, 63 | part: &[u8], 64 | ) -> Result 65 | { 66 | let sign_key = prepare_sign_key(sign_key)?; 67 | let key: SymmetricKey = content_key.parse()?; 68 | 69 | let next_file_key = StdFileEncryptor::upload_part_start( 70 | base_url, 71 | url_prefix, 72 | auth_token, 73 | jwt, 74 | session_id, 75 | end, 76 | sequence, 77 | &key, 78 | sign_key.as_ref(), 79 | part, 80 | ) 81 | .await?; 82 | 83 | Ok(export_core_sym_key_to_string(next_file_key)?) 84 | } 85 | 86 | #[allow(clippy::too_many_arguments)] 87 | pub async fn upload_part( 88 | base_url: String, 89 | url_prefix: Option, 90 | auth_token: &str, 91 | jwt: &str, 92 | session_id: &str, 93 | end: bool, 94 | sequence: i32, 95 | content_key: &str, 96 | sign_key: Option<&str>, 97 | part: &[u8], 98 | ) -> Result 99 | { 100 | let sign_key = prepare_sign_key(sign_key)?; 101 | let key = import_core_sym_key(content_key)?; 102 | 103 | let next_file_key = StdFileEncryptor::upload_part( 104 | base_url, 105 | url_prefix, 106 | auth_token, 107 | jwt, 108 | session_id, 109 | end, 110 | sequence, 111 | &key, 112 | sign_key.as_ref(), 113 | part, 114 | ) 115 | .await?; 116 | 117 | Ok(export_core_sym_key_to_string(next_file_key)?) 118 | } 119 | -------------------------------------------------------------------------------- /crypto/src/util_req_full/mod.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_common::user::Claims; 2 | 3 | pub mod file; 4 | pub mod group; 5 | pub mod user; 6 | 7 | enum SessionKind 8 | { 9 | Invite, 10 | Join, 11 | UserGroup, 12 | } 13 | 14 | #[cfg(not(feature = "export"))] 15 | pub(crate) type JwtRes = Result; 16 | 17 | #[cfg(feature = "export")] 18 | pub(crate) type JwtRes = Result; 19 | 20 | #[allow(clippy::needless_question_mark)] 21 | pub fn decode_jwt(token: &str) -> JwtRes 22 | { 23 | Ok(sentc_crypto_utils::jwt::decode_jwt(token)?) 24 | } 25 | -------------------------------------------------------------------------------- /crypto_core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc-crypto-core" 3 | version.workspace = true 4 | edition.workspace = true 5 | description = "The core of sentc encryption sdk with all alg." 6 | license-file.workspace = true 7 | authors.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | include = [ 13 | "Cargo.toml", 14 | "../LICENSE", 15 | "src/**/*", 16 | ] 17 | 18 | [dependencies] 19 | rand_core = { version = "0.6.3", default-features = false, features = ["getrandom"] } 20 | sha2 = { version = "0.10.2", default-features = false } 21 | 22 | [features] 23 | default = ["default_env"] 24 | 25 | # Descibe the used env for the crng 26 | default_env = [] -------------------------------------------------------------------------------- /crypto_core/src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | pub enum Error 3 | { 4 | DecryptionFailedCiphertextShort, 5 | 6 | KeyCreationFailed, 7 | 8 | EncryptionFailed, 9 | EncryptionFailedRng, 10 | DecryptionFailed, 11 | 12 | PwHashFailed, 13 | PwSplitFailedLeft, 14 | PwSplitFailedRight, 15 | HashAuthKeyFailed, 16 | 17 | KeyDecryptFailed, 18 | KeyDecryptionVerifyFailed, 19 | 20 | SignKeyCreateFailed, 21 | InitSignFailed, 22 | DataToSignTooShort, 23 | InitVerifyFailed, 24 | 25 | AlgNotFound, 26 | 27 | DecodePrivateKeyFailed, 28 | 29 | HmacAuthFailedLength, 30 | 31 | OpeRangeError, 32 | OpeHdgInvalidInputs, 33 | OpeStringToLarge, 34 | } 35 | -------------------------------------------------------------------------------- /crypto_core/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Sentclose crypto crate 2 | //! This create is non_std with alloc 3 | //! 4 | //! used alg: 5 | //! - Password hashing 6 | //! - argon2 7 | //! - symmetric encryption: 8 | //! - aes gcm 9 | //! - asymmetric encryption: 10 | //! - ecies based on x25519 11 | //! - signing 12 | //! - ed25519 13 | //! - hmac 14 | //! - hmac sha256 15 | //! 16 | //! This create can be used as stand-alone version without the sentclose api 17 | 18 | #![no_std] 19 | #![allow(clippy::infallible_destructuring_match, clippy::tabs_in_doc_comments, clippy::from_over_into)] 20 | 21 | extern crate alloc; 22 | 23 | pub mod cryptomat; 24 | mod error; 25 | pub mod group; 26 | pub mod user; 27 | 28 | use rand_core::{CryptoRng, OsRng, RngCore}; 29 | 30 | pub use self::error::Error; 31 | 32 | fn get_rand() -> impl CryptoRng + RngCore 33 | { 34 | #[cfg(feature = "default_env")] 35 | OsRng 36 | } 37 | 38 | pub fn generate_user_register_data() -> Result<([u8; 20], [u8; 40]), Error> 39 | { 40 | let mut identifier = [0u8; 20]; 41 | let mut password = [0u8; 40]; 42 | 43 | let mut rng = get_rand(); 44 | 45 | rng.try_fill_bytes(&mut identifier) 46 | .map_err(|_| Error::KeyCreationFailed)?; 47 | 48 | rng.try_fill_bytes(&mut password) 49 | .map_err(|_| Error::KeyCreationFailed)?; 50 | 51 | Ok((identifier, password)) 52 | } 53 | 54 | pub fn split_sig_and_data(data_with_sig: &[u8], len: usize) -> Result<(&[u8], &[u8]), Error> 55 | { 56 | if data_with_sig.len() <= len { 57 | return Err(Error::DataToSignTooShort); 58 | } 59 | 60 | //split sign and data 61 | let sig = &data_with_sig[..len]; 62 | let data = &data_with_sig[len..]; 63 | 64 | Ok((sig, data)) 65 | } 66 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc-crypto-fips-keys" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | authors.workspace = true 7 | homepage.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | description = "Fips compliant key impl with openssl" 13 | 14 | include = [ 15 | "Cargo.toml", 16 | "../LICENSE", 17 | "src/**/*", 18 | ] 19 | 20 | [dependencies] 21 | sentc-crypto-core.workspace = true 22 | sentc-crypto-utils = { workspace = true, optional = true } 23 | sentc-crypto-common = { workspace = true, optional = true } 24 | 25 | openssl = { version = "0.10.64", default-features = false } 26 | 27 | digest = "0.10.7" 28 | 29 | base64ct = { workspace = true, optional = true } 30 | serde = { workspace = true, optional = true } 31 | serde_json = { workspace = true, optional = true } 32 | 33 | [features] 34 | wrapper = ["sentc-crypto-utils", "sentc-crypto-common", "serde", "serde_json"] 35 | full = ["wrapper", "sentc-crypto-utils/encryption", "base64ct"] -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/core/hmac.rs: -------------------------------------------------------------------------------- 1 | use openssl::hash::MessageDigest; 2 | use openssl::memcmp; 3 | use openssl::pkey::{Id, PKey, Private}; 4 | use openssl::sign::Signer; 5 | use sentc_crypto_core::cryptomat::{SearchableKey, SearchableKeyComposer, SearchableKeyGen, SymKey}; 6 | use sentc_crypto_core::{crypto_alg_str_impl, Error}; 7 | 8 | use crate::core::{export_sk, sym}; 9 | use crate::import_export_openssl; 10 | 11 | pub const FIPS_OPENSSL_HMAC_SHA256_OUTPUT: &str = "fips_openssl_HMAC-SHA256"; 12 | 13 | pub struct HmacKey(PKey); 14 | 15 | import_export_openssl!(HmacKey, import_sk, export_sk); 16 | crypto_alg_str_impl!(HmacKey, FIPS_OPENSSL_HMAC_SHA256_OUTPUT); 17 | 18 | impl SearchableKey for HmacKey 19 | { 20 | fn encrypt_key_with_master_key(&self, master_key: &M) -> Result, Error> 21 | { 22 | master_key.encrypt(&export_sk(&self.0)?) 23 | } 24 | 25 | fn encrypt_searchable(&self, data: &[u8]) -> Result, Error> 26 | { 27 | let mut signer = Signer::new(MessageDigest::sha256(), &self.0).map_err(|_| Error::HmacAuthFailedLength)?; 28 | signer 29 | .update(data) 30 | .map_err(|_| Error::HmacAuthFailedLength)?; 31 | 32 | signer 33 | .sign_to_vec() 34 | .map_err(|_| Error::HmacAuthFailedLength) 35 | } 36 | 37 | fn verify_encrypted_searchable(&self, data: &[u8], check: &[u8]) -> Result 38 | { 39 | let sign = self.encrypt_searchable(data)?; 40 | 41 | Ok(memcmp::eq(&sign, check)) 42 | } 43 | } 44 | 45 | impl SearchableKeyGen for HmacKey 46 | { 47 | type SearchableKey = Self; 48 | 49 | fn generate() -> Result 50 | { 51 | let secret = sym::raw_generate()?; 52 | 53 | let key = PKey::hmac(&secret).map_err(|_| Error::KeyCreationFailed)?; 54 | 55 | Ok(Self(key)) 56 | } 57 | } 58 | 59 | impl SearchableKeyComposer for HmacKey 60 | { 61 | type Key = Self; 62 | 63 | fn decrypt_by_master_key(master_key: &M, encrypted_key: &[u8], alg_str: &str) -> Result 64 | { 65 | if alg_str != FIPS_OPENSSL_HMAC_SHA256_OUTPUT { 66 | return Err(Error::AlgNotFound); 67 | } 68 | 69 | let key = master_key.decrypt(encrypted_key)?; 70 | 71 | Self::try_from(key) 72 | } 73 | } 74 | 75 | fn import_sk(key: &[u8]) -> Result, Error> 76 | { 77 | PKey::private_key_from_raw_bytes(key, Id::HMAC).map_err(|_e| Error::KeyCreationFailed) 78 | } 79 | 80 | #[cfg(test)] 81 | mod test 82 | { 83 | use super::*; 84 | 85 | #[test] 86 | fn test_create_hmac_key() 87 | { 88 | openssl::provider::Provider::load(None, "fips").unwrap(); 89 | let _ = HmacKey::generate().unwrap(); 90 | } 91 | 92 | #[test] 93 | fn test_plain_auth_msg() 94 | { 95 | openssl::provider::Provider::load(None, "fips").unwrap(); 96 | 97 | let msg = "Hello world üöäéèßê°"; 98 | 99 | let out = HmacKey::generate().unwrap(); 100 | 101 | let mac = out.encrypt_searchable(msg.as_bytes()).unwrap(); 102 | 103 | let verify = out 104 | .verify_encrypted_searchable(msg.as_bytes(), &mac) 105 | .unwrap(); 106 | 107 | assert!(verify); 108 | } 109 | 110 | #[test] 111 | fn test_not_verify_with_wrong_key() 112 | { 113 | openssl::provider::Provider::load(None, "fips").unwrap(); 114 | 115 | let msg = "Hello world üöäéèßê°"; 116 | 117 | let out = HmacKey::generate().unwrap(); 118 | let out2 = HmacKey::generate().unwrap(); 119 | 120 | let mac = out.encrypt_searchable(msg.as_bytes()).unwrap(); 121 | 122 | let verify = out2 123 | .verify_encrypted_searchable(msg.as_bytes(), &mac) 124 | .unwrap(); 125 | 126 | assert!(!verify); 127 | } 128 | 129 | #[test] 130 | fn test_not_producing_the_same_output_with_different_keys() 131 | { 132 | openssl::provider::Provider::load(None, "fips").unwrap(); 133 | 134 | let msg = "Hello world üöäéèßê°"; 135 | 136 | let out = HmacKey::generate().unwrap(); 137 | let out2 = HmacKey::generate().unwrap(); 138 | 139 | let mac1 = out.encrypt_searchable(msg.as_bytes()).unwrap(); 140 | 141 | let mac2 = out2.encrypt_searchable(msg.as_bytes()).unwrap(); 142 | 143 | assert_ne!(mac1, mac2); 144 | } 145 | 146 | #[test] 147 | fn test_producing_the_same_output_with_same_keys() 148 | { 149 | openssl::provider::Provider::load(None, "fips").unwrap(); 150 | 151 | let msg = "Hello world üöäéèßê°"; 152 | 153 | let out = HmacKey::generate().unwrap(); 154 | 155 | let mac1 = out.encrypt_searchable(msg.as_bytes()).unwrap(); 156 | 157 | let mac2 = out.encrypt_searchable(msg.as_bytes()).unwrap(); 158 | 159 | assert_eq!(mac1, mac2); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/core/mod.rs: -------------------------------------------------------------------------------- 1 | use openssl::pkey::{HasPrivate, PKey}; 2 | use sentc_crypto_core::Error; 3 | 4 | pub mod asym; 5 | pub mod hmac; 6 | pub mod pw_hash; 7 | pub mod sign; 8 | pub mod sortable; 9 | pub mod sym; 10 | 11 | fn export_sk(key: &PKey) -> Result, Error> 12 | { 13 | key.raw_private_key().map_err(|_e| Error::KeyCreationFailed) 14 | } 15 | 16 | #[macro_export] 17 | macro_rules! import_export_openssl { 18 | ($st:ty,$import_k:ident, $export_k:ident) => { 19 | impl $st 20 | { 21 | pub fn export(&self) -> Result, Error> 22 | { 23 | $export_k(&self.0) 24 | } 25 | } 26 | 27 | impl TryFrom> for $st 28 | { 29 | type Error = sentc_crypto_core::Error; 30 | 31 | fn try_from(value: Vec) -> Result 32 | { 33 | Ok(Self($import_k(&value)?)) 34 | } 35 | } 36 | 37 | impl<'a> TryFrom<&'a [u8]> for $st 38 | { 39 | type Error = sentc_crypto_core::Error; 40 | 41 | fn try_from(value: &'a [u8]) -> Result 42 | { 43 | Ok(Self($import_k(value)?)) 44 | } 45 | } 46 | 47 | impl TryInto> for $st 48 | { 49 | type Error = sentc_crypto_core::Error; 50 | 51 | fn try_into(self) -> Result, Self::Error> 52 | { 53 | $export_k(&self.0) 54 | } 55 | } 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/core/sortable.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_core::cryptomat::{SortableKey, SortableKeyComposer, SortableKeyGen, SymKey}; 2 | use sentc_crypto_core::{crypto_alg_str_impl, Error}; 3 | 4 | pub const FIPS_OPENSSL_SORTABLE: &str = "fips_openssl_sortable_none"; 5 | 6 | pub struct NonSortableKeys; 7 | 8 | crypto_alg_str_impl!(NonSortableKeys, FIPS_OPENSSL_SORTABLE); 9 | 10 | impl SortableKey for NonSortableKeys 11 | { 12 | fn encrypt_key_with_master_key(&self, _master_key: &M) -> Result, Error> 13 | { 14 | Ok(Default::default()) 15 | } 16 | 17 | fn encrypt_sortable(&self, _data: u64) -> Result 18 | { 19 | Err(Error::AlgNotFound) 20 | } 21 | } 22 | 23 | impl SortableKeyGen for NonSortableKeys 24 | { 25 | type SortableKey = Self; 26 | 27 | fn generate() -> Result 28 | { 29 | Ok(Self) 30 | } 31 | } 32 | 33 | impl SortableKeyComposer for NonSortableKeys 34 | { 35 | type Key = Self; 36 | 37 | fn decrypt_by_master_key(_master_key: &M, _encrypted_key: &[u8], alg_str: &str) -> Result 38 | { 39 | if alg_str != FIPS_OPENSSL_SORTABLE { 40 | return Err(Error::AlgNotFound); 41 | } 42 | 43 | Ok(Self) 44 | } 45 | } 46 | 47 | #[cfg(test)] 48 | mod test 49 | { 50 | use super::*; 51 | 52 | #[test] 53 | fn test_gen_key() 54 | { 55 | let _ = NonSortableKeys::generate().unwrap(); 56 | } 57 | 58 | #[test] 59 | fn test_encrypt() 60 | { 61 | let key = NonSortableKeys::generate().unwrap(); 62 | 63 | let numbers = [262u64, 300, 1000, 65531]; 64 | 65 | for number in numbers { 66 | let res = key.encrypt_sortable(number); 67 | 68 | //not implemented for fips 69 | assert!(matches!(res, Err(Error::AlgNotFound))); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::infallible_destructuring_match, clippy::tabs_in_doc_comments, clippy::from_over_into)] 2 | 3 | pub mod core; 4 | #[cfg(feature = "wrapper")] 5 | pub mod util; 6 | 7 | //Load openssl in fips mode: openssl::provider::Provider::load(None, "fips")?; 8 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/util/crypto/asym.rs: -------------------------------------------------------------------------------- 1 | use openssl::base64::{decode_block, encode_block}; 2 | use sentc_crypto_common::crypto::EncryptedHead; 3 | use sentc_crypto_common::user::{UserPublicKeyData, UserVerifyKeyData}; 4 | use sentc_crypto_core::cryptomat::Sk; 5 | use sentc_crypto_utils::cryptomat::{PkFromUserKeyWrapper, SignKWrapper, SkCryptoWrapper, VerifyKFromUserKeyWrapper}; 6 | use sentc_crypto_utils::error::SdkUtilError; 7 | 8 | use crate::core::asym::RsaPk; 9 | use crate::util::export::import_public_key_from_pem_with_alg; 10 | use crate::util::{PublicKey, SecretKey, VerifyKey}; 11 | 12 | impl PkFromUserKeyWrapper for PublicKey 13 | { 14 | type CorePk = RsaPk; 15 | 16 | fn encrypt_string_with_user_key(reply_public_key: &UserPublicKeyData, data: &str) -> Result 17 | { 18 | let encrypted = Self::encrypt_with_user_key(reply_public_key, data.as_bytes())?; 19 | 20 | Ok(encode_block(&encrypted)) 21 | } 22 | 23 | fn encrypt_string_with_user_key_with_sign( 24 | reply_public_key: &UserPublicKeyData, 25 | data: &str, 26 | sign_key: &impl SignKWrapper, 27 | ) -> Result 28 | { 29 | let encrypted = Self::encrypt_with_user_key_with_sign(reply_public_key, data.as_bytes(), sign_key)?; 30 | 31 | Ok(encode_block(&encrypted)) 32 | } 33 | 34 | fn from_user_key(reply_public_key: &UserPublicKeyData) -> Result 35 | { 36 | import_public_key_from_pem_with_alg(&reply_public_key.public_key_pem, &reply_public_key.public_key_alg) 37 | } 38 | } 39 | 40 | impl SkCryptoWrapper for SecretKey 41 | { 42 | fn decrypt_raw(&self, encrypted_data: &[u8], head: &EncryptedHead, verify_key: Option<&UserVerifyKeyData>) -> Result, SdkUtilError> 43 | { 44 | match &head.sign { 45 | None => Ok(self.key.decrypt(encrypted_data)?), 46 | Some(h) => { 47 | match verify_key { 48 | None => { 49 | let (_, encrypted_data_without_sig) = VerifyKey::split_sig_and_data(&h.alg, encrypted_data)?; 50 | Ok(self.key.decrypt(encrypted_data_without_sig)?) 51 | }, 52 | Some(vk) => { 53 | let encrypted_data_without_sig = VerifyKey::verify_with_user_key(vk, encrypted_data, h)?; 54 | Ok(self.key.decrypt(encrypted_data_without_sig)?) 55 | }, 56 | } 57 | }, 58 | } 59 | } 60 | 61 | fn decrypt_string(&self, encrypted_data_with_head: &str, verify_key: Option<&UserVerifyKeyData>) -> Result 62 | { 63 | let encrypted = decode_block(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 64 | 65 | let decrypted = self.decrypt(&encrypted, verify_key)?; 66 | 67 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/util/crypto/mod.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use openssl::base64::{decode_block, encode_block}; 4 | use sentc_crypto_common::content_sortable::SortableEncryptOutput; 5 | use sentc_crypto_common::SymKeyId; 6 | use sentc_crypto_core::cryptomat::SortableKeyComposer; 7 | use sentc_crypto_utils::cryptomat::{KeyToString, SortableKeyComposerWrapper, SortableKeyWrapper}; 8 | use sentc_crypto_utils::error::SdkUtilError; 9 | use sentc_crypto_utils::{from_string_impl, to_string_try_impl}; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | use crate::core::hmac::HmacKey as CoreHmacKey; 13 | use crate::core::sortable::NonSortableKeys; 14 | 15 | mod asym; 16 | mod searchable; 17 | mod sign; 18 | mod symmetric_key; 19 | 20 | pub struct HmacKey 21 | { 22 | pub key: CoreHmacKey, 23 | pub key_id: SymKeyId, 24 | } 25 | 26 | to_string_try_impl!(HmacKey, HmacFormatExport); 27 | from_string_impl!(HmacKey, HmacFormatExport); 28 | 29 | #[derive(Serialize, Deserialize)] 30 | pub struct HmacFormatExport 31 | { 32 | key: String, 33 | key_id: SymKeyId, 34 | } 35 | 36 | impl TryFrom for HmacFormatExport 37 | { 38 | type Error = SdkUtilError; 39 | 40 | fn try_from(value: HmacKey) -> Result 41 | { 42 | let key = encode_block(&value.key.export()?); 43 | 44 | Ok(Self { 45 | key, 46 | key_id: value.key_id, 47 | }) 48 | } 49 | } 50 | 51 | impl<'a> TryFrom<&'a HmacKey> for HmacFormatExport 52 | { 53 | type Error = SdkUtilError; 54 | 55 | fn try_from(value: &'a HmacKey) -> Result 56 | { 57 | let key = encode_block(&value.key.export()?); 58 | 59 | Ok(Self { 60 | key, 61 | key_id: value.key_id.clone(), 62 | }) 63 | } 64 | } 65 | 66 | impl TryInto for HmacFormatExport 67 | { 68 | type Error = SdkUtilError; 69 | 70 | fn try_into(self) -> Result 71 | { 72 | let bytes = decode_block(&self.key).map_err(|_| SdkUtilError::ImportSymmetricKeyFailed)?; 73 | 74 | Ok(HmacKey { 75 | key: CoreHmacKey::try_from(bytes)?, 76 | key_id: self.key_id, 77 | }) 78 | } 79 | } 80 | 81 | //__________________________________________________________________________________________________ 82 | 83 | //Sortable key is not complained with fips 84 | 85 | pub struct SortableKey 86 | { 87 | pub key: NonSortableKeys, 88 | pub key_id: SymKeyId, 89 | } 90 | 91 | impl KeyToString for SortableKey 92 | { 93 | fn to_string(self) -> Result 94 | { 95 | Ok(self.key_id) 96 | } 97 | 98 | fn to_string_ref(&self) -> Result 99 | { 100 | Ok(self.key_id.clone()) 101 | } 102 | } 103 | 104 | impl FromStr for SortableKey 105 | { 106 | type Err = SdkUtilError; 107 | 108 | fn from_str(s: &str) -> Result 109 | { 110 | Ok(Self { 111 | key: NonSortableKeys, 112 | key_id: s.to_string(), 113 | }) 114 | } 115 | } 116 | 117 | impl SortableKeyComposerWrapper for SortableKey 118 | { 119 | type SortableKeyWrapper = Self; 120 | type Composer = NonSortableKeys; 121 | 122 | fn from_inner(inner: <::Composer as SortableKeyComposer>::Key, id: String) -> Self::SortableKeyWrapper 123 | { 124 | Self { 125 | key: inner, 126 | key_id: id, 127 | } 128 | } 129 | } 130 | 131 | impl SortableKeyWrapper for SortableKey 132 | { 133 | type Inner = NonSortableKeys; 134 | 135 | fn get_id(&self) -> &str 136 | { 137 | &self.key_id 138 | } 139 | 140 | fn get_key(&self) -> &Self::Inner 141 | { 142 | &self.key 143 | } 144 | 145 | fn encrypt_raw_string(&self, _data: &str, _max_len: Option) -> Result 146 | { 147 | Err(SdkUtilError::AlgNotFound) 148 | } 149 | 150 | fn encrypt_string(&self, _data: &str, _max_len: Option) -> Result 151 | { 152 | Err(SdkUtilError::AlgNotFound) 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/util/crypto/searchable.rs: -------------------------------------------------------------------------------- 1 | use base64ct::{Base64UrlUnpadded, Encoding}; 2 | use sentc_crypto_core::cryptomat::SearchableKey; 3 | use sentc_crypto_utils::cryptomat::SearchableKeyWrapper; 4 | use sentc_crypto_utils::error::SdkUtilError; 5 | use sentc_crypto_utils::search_key_composer; 6 | 7 | use crate::core::hmac::HmacKey as CoreHmacKey; 8 | use crate::util::HmacKey; 9 | 10 | search_key_composer!(HmacKey, CoreHmacKey); 11 | 12 | impl SearchableKeyWrapper for HmacKey 13 | { 14 | type Inner = CoreHmacKey; 15 | 16 | fn get_id(&self) -> &str 17 | { 18 | &self.key_id 19 | } 20 | 21 | fn get_key(&self) -> &Self::Inner 22 | { 23 | &self.key 24 | } 25 | 26 | fn search_bytes(&self, data: &[u8]) -> Result 27 | { 28 | let hash = self.key.encrypt_searchable(data)?; 29 | 30 | Ok(Base64UrlUnpadded::encode_string(&hash)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/util/crypto/sign.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_common::crypto::SignHead; 2 | use sentc_crypto_common::user::UserVerifyKeyData; 3 | use sentc_crypto_core::cryptomat::{CryptoAlg, SignK}; 4 | use sentc_crypto_utils::cryptomat::{SignKCryptoWrapper, VerifyKFromUserKeyWrapper}; 5 | use sentc_crypto_utils::error::SdkUtilError; 6 | 7 | use crate::core::sign::{split_sig_and_data, Ed25519FIPSVerifyK, FIPS_OPENSSL_ED25519}; 8 | use crate::util::export::import_verify_key_from_pem_with_alg; 9 | use crate::util::{SignKey, VerifyKey}; 10 | 11 | impl SignKCryptoWrapper for SignKey 12 | { 13 | fn sign_with_head(&self, data: &[u8]) -> Result<(SignHead, Vec), SdkUtilError> 14 | { 15 | let sig = self.key.sign(data)?; 16 | 17 | Ok(( 18 | SignHead { 19 | id: self.key_id.clone(), 20 | alg: self.key.get_alg_str().to_string(), 21 | }, 22 | sig, 23 | )) 24 | } 25 | } 26 | 27 | impl VerifyKFromUserKeyWrapper for VerifyKey 28 | { 29 | type CoreVk = Ed25519FIPSVerifyK; 30 | 31 | fn split_sig_and_data<'a>(alg: &str, data_with_sign: &'a [u8]) -> Result<(&'a [u8], &'a [u8]), SdkUtilError> 32 | { 33 | if alg != FIPS_OPENSSL_ED25519 { 34 | return Err(SdkUtilError::AlgNotFound); 35 | } 36 | 37 | Ok(split_sig_and_data(data_with_sign)?) 38 | } 39 | 40 | fn from_user_key(verify_key: &UserVerifyKeyData) -> Result 41 | { 42 | import_verify_key_from_pem_with_alg(&verify_key.verify_key_pem, &verify_key.verify_key_alg) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/util/crypto/symmetric_key.rs: -------------------------------------------------------------------------------- 1 | use openssl::base64::{decode_block, encode_block}; 2 | use sentc_crypto_common::crypto::EncryptedHead; 3 | use sentc_crypto_common::user::UserVerifyKeyData; 4 | use sentc_crypto_core::cryptomat::SymKey; 5 | use sentc_crypto_utils::cryptomat::{SignKWrapper, SymKeyCrypto}; 6 | use sentc_crypto_utils::error::SdkUtilError; 7 | 8 | use crate::util::{SymmetricKey, VerifyKey}; 9 | 10 | impl SymKeyCrypto for SymmetricKey 11 | { 12 | type VerifyKey = VerifyKey; 13 | 14 | fn encrypt_raw(&self, data: &[u8]) -> Result<(EncryptedHead, Vec), SdkUtilError> 15 | { 16 | let encrypted = self.key.encrypt(data)?; 17 | 18 | Ok(( 19 | EncryptedHead { 20 | id: self.key_id.to_string(), 21 | sign: None, 22 | }, 23 | encrypted, 24 | )) 25 | } 26 | 27 | fn encrypt_raw_with_sign(&self, data: &[u8], sign_key: &impl SignKWrapper) -> Result<(EncryptedHead, Vec), SdkUtilError> 28 | { 29 | let encrypted = self.key.encrypt(data)?; 30 | 31 | let (sign_head, data_with_sign) = sign_key.sign_with_head(&encrypted)?; 32 | 33 | Ok(( 34 | EncryptedHead { 35 | id: self.key_id.to_string(), 36 | sign: Some(sign_head), 37 | }, 38 | data_with_sign, 39 | )) 40 | } 41 | 42 | fn encrypt_raw_with_aad(&self, data: &[u8], aad: &[u8]) -> Result<(EncryptedHead, Vec), SdkUtilError> 43 | { 44 | let encrypted = self.key.encrypt_with_aad(data, aad)?; 45 | 46 | Ok(( 47 | EncryptedHead { 48 | id: self.key_id.to_string(), 49 | sign: None, 50 | }, 51 | encrypted, 52 | )) 53 | } 54 | 55 | fn encrypt_raw_with_aad_with_sign(&self, data: &[u8], aad: &[u8], sign_key: &impl SignKWrapper) 56 | -> Result<(EncryptedHead, Vec), SdkUtilError> 57 | { 58 | let encrypted = self.key.encrypt_with_aad(data, aad)?; 59 | 60 | let (sign_head, data_with_sign) = sign_key.sign_with_head(&encrypted)?; 61 | 62 | Ok(( 63 | EncryptedHead { 64 | id: self.key_id.to_string(), 65 | sign: Some(sign_head), 66 | }, 67 | data_with_sign, 68 | )) 69 | } 70 | 71 | fn decrypt_raw(&self, encrypted_data: &[u8], head: &EncryptedHead, verify_key: Option<&UserVerifyKeyData>) -> Result, SdkUtilError> 72 | { 73 | let data_to_decrypt = Self::prepare_decrypt(encrypted_data, head, verify_key)?; 74 | 75 | Ok(self.key.decrypt(data_to_decrypt)?) 76 | } 77 | 78 | fn decrypt_raw_with_aad( 79 | &self, 80 | encrypted_data: &[u8], 81 | aad: &[u8], 82 | head: &EncryptedHead, 83 | verify_key: Option<&UserVerifyKeyData>, 84 | ) -> Result, SdkUtilError> 85 | { 86 | let data_to_decrypt = Self::prepare_decrypt(encrypted_data, head, verify_key)?; 87 | 88 | Ok(self.key.decrypt_with_aad(data_to_decrypt, aad)?) 89 | } 90 | 91 | fn encrypt_string(&self, data: &str) -> Result 92 | { 93 | let encrypted = self.encrypt(data.as_bytes())?; 94 | 95 | Ok(encode_block(&encrypted)) 96 | } 97 | 98 | fn encrypt_string_with_sign(&self, data: &str, sign_key: &impl SignKWrapper) -> Result 99 | { 100 | let encrypted = self.encrypt_with_sign(data.as_bytes(), sign_key)?; 101 | 102 | Ok(encode_block(&encrypted)) 103 | } 104 | 105 | fn encrypt_string_with_aad(&self, data: &str, aad: &str) -> Result 106 | { 107 | let encrypted = self.encrypt_with_aad(data.as_bytes(), aad.as_bytes())?; 108 | 109 | Ok(encode_block(&encrypted)) 110 | } 111 | 112 | fn encrypt_string_with_aad_with_sign(&self, data: &str, aad: &str, sign_key: &impl SignKWrapper) -> Result 113 | { 114 | let encrypted = self.encrypt_with_aad_with_sign(data.as_bytes(), aad.as_bytes(), sign_key)?; 115 | 116 | Ok(encode_block(&encrypted)) 117 | } 118 | 119 | fn decrypt_string(&self, encrypted_data_with_head: &str, verify_key: Option<&UserVerifyKeyData>) -> Result 120 | { 121 | let encrypted = decode_block(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 122 | 123 | let decrypted = self.decrypt(&encrypted, verify_key)?; 124 | 125 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 126 | } 127 | 128 | fn decrypt_string_with_aad( 129 | &self, 130 | encrypted_data_with_head: &str, 131 | aad: &str, 132 | verify_key: Option<&UserVerifyKeyData>, 133 | ) -> Result 134 | { 135 | let encrypted = decode_block(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 136 | 137 | let decrypted = self.decrypt_with_aad(&encrypted, aad.as_bytes(), verify_key)?; 138 | 139 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /crypto_keys/crypto_fips_keys/src/util/export.rs: -------------------------------------------------------------------------------- 1 | use openssl::base64::{decode_block, encode_block}; 2 | use sentc_crypto_utils::error::SdkUtilError; 3 | use sentc_crypto_utils::{export_key_to_pem, import_key_from_pem}; 4 | 5 | use crate::core::asym::{RsaPk, FIPS_OPENSSL_RSA_OAEP_WRAP}; 6 | use crate::core::sign::{Ed25519FIPSSig, Ed25519FIPSVerifyK, FIPS_OPENSSL_ED25519}; 7 | 8 | pub fn import_public_key_from_pem_with_alg(public_key: &str, alg: &str) -> Result 9 | { 10 | if alg != FIPS_OPENSSL_RSA_OAEP_WRAP { 11 | return Err(SdkUtilError::AlgNotFound); 12 | } 13 | 14 | let bytes = import_key_from_pem(public_key)?; 15 | 16 | Ok(RsaPk::try_from(bytes)?) 17 | } 18 | 19 | pub fn import_verify_key_from_pem_with_alg(verify_key: &str, alg: &str) -> Result 20 | { 21 | if alg != FIPS_OPENSSL_ED25519 { 22 | return Err(SdkUtilError::AlgNotFound); 23 | } 24 | 25 | let bytes = import_key_from_pem(verify_key)?; 26 | 27 | Ok(Ed25519FIPSVerifyK::try_from(bytes)?) 28 | } 29 | 30 | pub fn export_raw_public_key_to_pem(key: &RsaPk) -> Result 31 | { 32 | export_key_to_pem(&key.export()?) 33 | } 34 | 35 | pub fn export_raw_verify_key_to_pem(key: &Ed25519FIPSVerifyK) -> Result 36 | { 37 | export_key_to_pem(&key.export()?) 38 | } 39 | 40 | pub fn sig_to_string(sig: &Ed25519FIPSSig) -> String 41 | { 42 | encode_block(sig.as_ref()) 43 | } 44 | 45 | pub fn import_sig_from_string(sig: &str, alg: &str) -> Result 46 | { 47 | if alg != FIPS_OPENSSL_ED25519 { 48 | return Err(SdkUtilError::AlgNotFound); 49 | } 50 | 51 | let bytes = decode_block(sig).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 52 | 53 | Ok(bytes.into()) 54 | } 55 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc-crypto-rec-keys" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | authors.workspace = true 7 | homepage.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | description = "The recommended keys. It uses a combination of openssl and oqs." 13 | 14 | include = [ 15 | "Cargo.toml", 16 | "../LICENSE", 17 | "src/**/*", 18 | ] 19 | 20 | [dependencies] 21 | sentc-crypto-core.workspace = true 22 | sentc-crypto-utils = { workspace = true, optional = true } 23 | sentc-crypto-common = { workspace = true, optional = true } 24 | sentc-crypto-fips-keys.workspace = true 25 | 26 | digest = "0.10.7" 27 | argon2 = "0.3" 28 | ope = "0.1.1" 29 | openssl = { version = "0.10.64", default-features = false } 30 | 31 | safe-oqs = { version = "0.10.0", default-features = false, features = ["std", "ml_kem", "ml_dsa"] } 32 | 33 | # key and data export 34 | serde_json = { workspace = true, optional = true } 35 | serde = { workspace = true, optional = true } 36 | 37 | [features] 38 | default = ["ecies_ml_kem_hybrid", "ed25519_ml_dsa_hybrid"] 39 | 40 | # asymmetric encryption 41 | ecies = [] 42 | ecies_ml_kem_hybrid = [] 43 | 44 | # sign 45 | ed25519 = [] 46 | ed25519_ml_dsa_hybrid = [] 47 | 48 | wrapper = ["sentc-crypto-utils", "serde", "serde_json", "sentc-crypto-common", "sentc-crypto-fips-keys/wrapper"] 49 | full = ["wrapper", "sentc-crypto-utils/encryption", "sentc-crypto-fips-keys/full"] -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/core/asym/mod.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_core::cryptomat::{CryptoAlg, Pk, SignK, Sk, SkComposer, StaticKeyPair, SymKey, VerifyK}; 2 | use sentc_crypto_core::Error; 3 | 4 | pub use crate::core::asym::ecies::ECIES_REC_OUTPUT; 5 | use crate::core::asym::ecies::{EciesPk, EciesSk}; 6 | pub use crate::core::asym::ecies_ml_kem_hybrid::ECIES_ML_KEM_REC_HYBRID_OUTPUT; 7 | use crate::core::asym::ecies_ml_kem_hybrid::{EciesMlKemHybridPk, EciesMlKemHybridSk}; 8 | pub use crate::core::asym::pqc_ml_kem::ML_KEM_REC_OUTPUT; 9 | use crate::core::asym::pqc_ml_kem::{MlKemPk, MlKemSk}; 10 | 11 | mod ecies; 12 | mod ecies_ml_kem_hybrid; 13 | mod pqc_ml_kem; 14 | 15 | macro_rules! deref_macro { 16 | ($self:expr, $method:ident $(, $args:expr)*) => { 17 | match $self { 18 | Self::Ecies(inner) => inner.$method($($args),*), 19 | Self::MlKem(inner) => inner.$method($($args),*), 20 | Self::EciesMlKemHybrid(inner) => inner.$method($($args),*), 21 | } 22 | }; 23 | } 24 | 25 | macro_rules! crypto_alg_impl { 26 | ($name:ty) => { 27 | impl CryptoAlg for $name 28 | { 29 | fn get_alg_str(&self) -> &'static str 30 | { 31 | deref_macro!(self, get_alg_str) 32 | } 33 | } 34 | }; 35 | } 36 | 37 | macro_rules! get_inner_key { 38 | ($st:ty,$t:ident) => { 39 | impl $st 40 | { 41 | pub fn ecies_from_bytes_owned(bytes: Vec) -> Result 42 | { 43 | Ok(Self::Ecies(bytes.try_into()?)) 44 | } 45 | 46 | pub fn ml_kem_from_bytes_owned(bytes: Vec) -> Self 47 | { 48 | Self::MlKem(bytes.into()) 49 | } 50 | 51 | pub fn ecies_ml_kem_hybrid_from_bytes_owned(bytes_x: Vec, bytes_k: Vec) -> Result 52 | { 53 | Ok(Self::EciesMlKemHybrid($t::from_bytes(bytes_x, bytes_k)?)) 54 | } 55 | } 56 | }; 57 | } 58 | 59 | #[derive(Clone)] 60 | pub enum PublicKey 61 | { 62 | Ecies(EciesPk), 63 | MlKem(MlKemPk), 64 | EciesMlKemHybrid(EciesMlKemHybridPk), 65 | } 66 | 67 | crypto_alg_impl!(PublicKey); 68 | get_inner_key!(PublicKey, EciesMlKemHybridPk); 69 | 70 | impl Pk for PublicKey 71 | { 72 | fn sign_public_key(&self, sign_key: &S) -> Result 73 | { 74 | deref_macro!(self, sign_public_key, sign_key) 75 | } 76 | 77 | fn verify_public_key(&self, verify_key: &V, sig: &V::Signature) -> Result 78 | { 79 | deref_macro!(self, verify_public_key, verify_key, sig) 80 | } 81 | 82 | fn encrypt(&self, data: &[u8]) -> Result, Error> 83 | { 84 | deref_macro!(self, encrypt, data) 85 | } 86 | } 87 | 88 | pub enum SecretKey 89 | { 90 | Ecies(EciesSk), 91 | MlKem(MlKemSk), 92 | EciesMlKemHybrid(EciesMlKemHybridSk), 93 | } 94 | 95 | crypto_alg_impl!(SecretKey); 96 | get_inner_key!(SecretKey, EciesMlKemHybridSk); 97 | 98 | impl Sk for SecretKey 99 | { 100 | fn encrypt_by_master_key(&self, master_key: &M) -> Result, Error> 101 | { 102 | deref_macro!(self, encrypt_by_master_key, master_key) 103 | } 104 | 105 | fn decrypt(&self, ciphertext: &[u8]) -> Result, Error> 106 | { 107 | deref_macro!(self, decrypt, ciphertext) 108 | } 109 | } 110 | 111 | impl SkComposer for SecretKey 112 | { 113 | type SecretKey = Self; 114 | 115 | fn decrypt_by_master_key(master_key: &M, encrypted_key: &[u8], alg_str: &str) -> Result 116 | { 117 | let bytes = master_key.decrypt(encrypted_key)?; 118 | 119 | let key = match alg_str { 120 | ECIES_REC_OUTPUT => Self::Ecies(bytes.try_into()?), 121 | ML_KEM_REC_OUTPUT => Self::MlKem(bytes.into()), 122 | ECIES_ML_KEM_REC_HYBRID_OUTPUT => Self::EciesMlKemHybrid(bytes.try_into()?), 123 | _ => return Err(Error::AlgNotFound), 124 | }; 125 | 126 | Ok(key) 127 | } 128 | } 129 | 130 | impl StaticKeyPair for SecretKey 131 | { 132 | type SecretKey = Self; 133 | type PublicKey = PublicKey; 134 | 135 | fn generate_static_keypair() -> Result<(Self::SecretKey, Self::PublicKey), Error> 136 | { 137 | #[cfg(feature = "ecies_ml_kem_hybrid")] 138 | let (sk, pk) = EciesMlKemHybridSk::generate_static_keypair()?; 139 | 140 | #[cfg(feature = "ecies")] 141 | let (sk, pk) = EciesSk::generate_static_keypair()?; 142 | 143 | Ok((sk.into(), pk.into())) 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/core/mod.rs: -------------------------------------------------------------------------------- 1 | use openssl::pkey::{HasPrivate, HasPublic, PKey}; 2 | use sentc_crypto_core::Error; 3 | 4 | pub mod asym; 5 | pub mod pw_hash; 6 | pub mod sign; 7 | pub mod sortable; 8 | 9 | pub mod sym 10 | { 11 | pub use sentc_crypto_fips_keys::core::sym::*; 12 | } 13 | 14 | pub mod hmac 15 | { 16 | pub use sentc_crypto_fips_keys::core::hmac::*; 17 | } 18 | 19 | fn export_pk(pk: &PKey) -> Result, Error> 20 | { 21 | pk.raw_public_key().map_err(|_e| Error::KeyCreationFailed) 22 | } 23 | 24 | fn export_sk(key: &PKey) -> Result, Error> 25 | { 26 | key.raw_private_key().map_err(|_e| Error::KeyCreationFailed) 27 | } 28 | 29 | #[macro_export] 30 | macro_rules! hybrid_import_export { 31 | ($st:ty,$import_k:ident, $export_k:ident) => { 32 | impl $st 33 | { 34 | pub fn prepare_export(&self) -> Result<(Vec, &[u8]), sentc_crypto_core::Error> 35 | { 36 | Ok(($export_k(&self.x)?, self.k.as_slice())) 37 | } 38 | 39 | pub fn from_bytes(bytes_x: Vec, bytes_k: Vec) -> Result 40 | { 41 | Ok(Self { 42 | x: $import_k(&bytes_x)?, 43 | k: bytes_k, 44 | }) 45 | } 46 | } 47 | }; 48 | } 49 | 50 | #[macro_export] 51 | macro_rules! hybrid_sk_from_bytes { 52 | ($st:ty,$import_k:ident) => { 53 | impl $st 54 | { 55 | fn import(bytes: &[u8]) -> Result 56 | { 57 | let x = &bytes[..32]; 58 | let k = &bytes[32..]; 59 | 60 | Ok(Self { 61 | x: $import_k(x)?, 62 | k: k.to_vec(), 63 | }) 64 | } 65 | } 66 | 67 | impl<'a> TryFrom<&'a [u8]> for $st 68 | { 69 | type Error = sentc_crypto_core::Error; 70 | 71 | fn try_from(value: &'a [u8]) -> Result 72 | { 73 | Self::import(value) 74 | } 75 | } 76 | 77 | impl TryFrom> for $st 78 | { 79 | type Error = sentc_crypto_core::Error; 80 | 81 | fn try_from(value: Vec) -> Result 82 | { 83 | Self::import(&value) 84 | } 85 | } 86 | }; 87 | } 88 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/core/sortable.rs: -------------------------------------------------------------------------------- 1 | use ope::{get_ope, OpeError, OpeKey}; 2 | use openssl::rand::rand_bytes; 3 | use sentc_crypto_core::cryptomat::{SortableKey, SortableKeyComposer, SortableKeyGen, SymKey}; 4 | use sentc_crypto_core::{as_ref_bytes_single_value, crypto_alg_str_impl, try_from_bytes_owned_single_value, try_from_bytes_single_value, Error}; 5 | 6 | pub const OPE_REC_OUT: &str = "OPE_REC-16"; 7 | 8 | pub struct OpeSortableKey(OpeKey); 9 | 10 | try_from_bytes_single_value!(OpeSortableKey); 11 | try_from_bytes_owned_single_value!(OpeSortableKey); 12 | as_ref_bytes_single_value!(OpeSortableKey); 13 | 14 | crypto_alg_str_impl!(OpeSortableKey, OPE_REC_OUT); 15 | 16 | impl SortableKey for OpeSortableKey 17 | { 18 | fn encrypt_key_with_master_key(&self, master_key: &M) -> Result, Error> 19 | { 20 | master_key.encrypt(&self.0) 21 | } 22 | 23 | fn encrypt_sortable(&self, data: u64) -> Result 24 | { 25 | if data > 65532 { 26 | return Err(Error::OpeStringToLarge); 27 | } 28 | 29 | let ope = get_ope(&self.0); 30 | 31 | let out = ope.encrypt(data); 32 | 33 | match out { 34 | Ok(o) => Ok(o), 35 | Err(err) => { 36 | match err { 37 | OpeError::HdgInvalidInputs => Err(Error::OpeHdgInvalidInputs), 38 | OpeError::OpeRange => Err(Error::OpeRangeError), 39 | } 40 | }, 41 | } 42 | } 43 | } 44 | 45 | impl SortableKeyGen for OpeSortableKey 46 | { 47 | type SortableKey = Self; 48 | 49 | fn generate() -> Result 50 | { 51 | let mut key = [0u8; 16]; 52 | rand_bytes(&mut key).map_err(|_| Error::KeyCreationFailed)?; 53 | 54 | Ok(Self(key)) 55 | } 56 | } 57 | 58 | impl SortableKeyComposer for OpeSortableKey 59 | { 60 | type Key = Self; 61 | 62 | fn decrypt_by_master_key(master_key: &M, encrypted_key: &[u8], alg_str: &str) -> Result 63 | { 64 | if alg_str != OPE_REC_OUT { 65 | return Err(Error::AlgNotFound); 66 | } 67 | 68 | let key = master_key.decrypt(encrypted_key)?; 69 | 70 | key.try_into() 71 | } 72 | } 73 | 74 | #[cfg(test)] 75 | mod test 76 | { 77 | use super::*; 78 | 79 | #[test] 80 | fn test_gen_key() 81 | { 82 | let _ = OpeSortableKey::generate().unwrap(); 83 | } 84 | 85 | #[test] 86 | fn test_encrypt() 87 | { 88 | let key = OpeSortableKey::generate().unwrap(); 89 | 90 | let numbers = [262u64, 300, 1000, 65531]; 91 | 92 | let mut out = [0u64; 4]; 93 | 94 | for (i, number) in numbers.iter().enumerate() { 95 | out[i] = key.encrypt_sortable(*number).unwrap(); 96 | } 97 | 98 | //check 99 | 100 | let mut past_item = 0; 101 | 102 | for item in out { 103 | assert!(past_item < item); 104 | 105 | past_item = item; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::infallible_destructuring_match, clippy::tabs_in_doc_comments, clippy::from_over_into)] 2 | 3 | pub mod core; 4 | #[cfg(feature = "wrapper")] 5 | pub mod util; 6 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/util/crypto/asym.rs: -------------------------------------------------------------------------------- 1 | use openssl::base64::{decode_block, encode_block}; 2 | use sentc_crypto_common::crypto::EncryptedHead; 3 | use sentc_crypto_common::user::{UserPublicKeyData, UserVerifyKeyData}; 4 | use sentc_crypto_core::cryptomat::Sk; 5 | use sentc_crypto_utils::cryptomat::{PkFromUserKeyWrapper, SignKWrapper, SkCryptoWrapper, VerifyKFromUserKeyWrapper}; 6 | use sentc_crypto_utils::error::SdkUtilError; 7 | 8 | use crate::core::asym::PublicKey as CorePk; 9 | use crate::util::export::import_public_key_from_pem_with_alg; 10 | use crate::util::{PublicKey, SecretKey, VerifyKey}; 11 | 12 | impl SkCryptoWrapper for SecretKey 13 | { 14 | fn decrypt_raw(&self, encrypted_data: &[u8], head: &EncryptedHead, verify_key: Option<&UserVerifyKeyData>) -> Result, SdkUtilError> 15 | { 16 | match &head.sign { 17 | None => Ok(self.key.decrypt(encrypted_data)?), 18 | Some(h) => { 19 | match verify_key { 20 | None => { 21 | let (_, encrypted_data_without_sig) = VerifyKey::split_sig_and_data(&h.alg, encrypted_data)?; 22 | Ok(self.key.decrypt(encrypted_data_without_sig)?) 23 | }, 24 | Some(vk) => { 25 | let encrypted_data_without_sig = VerifyKey::verify_with_user_key(vk, encrypted_data, h)?; 26 | Ok(self.key.decrypt(encrypted_data_without_sig)?) 27 | }, 28 | } 29 | }, 30 | } 31 | } 32 | 33 | fn decrypt_string(&self, encrypted_data_with_head: &str, verify_key: Option<&UserVerifyKeyData>) -> Result 34 | { 35 | let encrypted = decode_block(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 36 | 37 | let decrypted = self.decrypt(&encrypted, verify_key)?; 38 | 39 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 40 | } 41 | } 42 | 43 | impl PkFromUserKeyWrapper for PublicKey 44 | { 45 | type CorePk = CorePk; 46 | 47 | fn encrypt_string_with_user_key(reply_public_key: &UserPublicKeyData, data: &str) -> Result 48 | { 49 | let encrypted = Self::encrypt_with_user_key(reply_public_key, data.as_bytes())?; 50 | 51 | Ok(encode_block(&encrypted)) 52 | } 53 | 54 | fn encrypt_string_with_user_key_with_sign( 55 | reply_public_key: &UserPublicKeyData, 56 | data: &str, 57 | sign_key: &impl SignKWrapper, 58 | ) -> Result 59 | { 60 | let encrypted = Self::encrypt_with_user_key_with_sign(reply_public_key, data.as_bytes(), sign_key)?; 61 | 62 | Ok(encode_block(&encrypted)) 63 | } 64 | 65 | fn from_user_key(reply_public_key: &UserPublicKeyData) -> Result 66 | { 67 | import_public_key_from_pem_with_alg(&reply_public_key.public_key_pem, &reply_public_key.public_key_alg) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/util/crypto/mod.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use openssl::base64::{decode_block, encode_block}; 4 | use sentc_crypto_common::SymKeyId; 5 | use sentc_crypto_utils::error::SdkUtilError; 6 | use sentc_crypto_utils::{from_string_impl, to_string_impl}; 7 | use serde::{Deserialize, Serialize}; 8 | 9 | use crate::core::sortable::OpeSortableKey; 10 | 11 | mod asym; 12 | mod sign; 13 | mod sortable; 14 | mod symmetric_key; 15 | 16 | pub struct SortableKey 17 | { 18 | pub key: OpeSortableKey, 19 | pub key_id: SymKeyId, 20 | } 21 | 22 | to_string_impl!(SortableKey, SortableFormatExport); 23 | from_string_impl!(SortableKey, SortableFormatExport); 24 | 25 | #[derive(Serialize, Deserialize)] 26 | pub enum SortableFormatExport 27 | { 28 | Ope16 29 | { 30 | key: String, key_id: SymKeyId 31 | }, 32 | } 33 | 34 | impl From for SortableFormatExport 35 | { 36 | fn from(value: SortableKey) -> Self 37 | { 38 | let key = encode_block(value.key.as_ref()); 39 | 40 | Self::Ope16 { 41 | key, 42 | key_id: value.key_id, 43 | } 44 | } 45 | } 46 | 47 | impl<'a> From<&'a SortableKey> for SortableFormatExport 48 | { 49 | fn from(value: &'a SortableKey) -> Self 50 | { 51 | let key = encode_block(value.key.as_ref()); 52 | 53 | Self::Ope16 { 54 | key, 55 | key_id: value.key_id.clone(), 56 | } 57 | } 58 | } 59 | 60 | impl TryInto for SortableFormatExport 61 | { 62 | type Error = SdkUtilError; 63 | 64 | fn try_into(self) -> Result 65 | { 66 | match self { 67 | SortableFormatExport::Ope16 { 68 | key, 69 | key_id, 70 | } => { 71 | let bytes = decode_block(&key).map_err(|_| SdkUtilError::ImportSymmetricKeyFailed)?; 72 | 73 | Ok(SortableKey { 74 | key: bytes.try_into()?, 75 | key_id, 76 | }) 77 | }, 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/util/crypto/sign.rs: -------------------------------------------------------------------------------- 1 | use sentc_crypto_common::crypto::SignHead; 2 | use sentc_crypto_common::user::UserVerifyKeyData; 3 | use sentc_crypto_core::cryptomat::{CryptoAlg, SignK}; 4 | use sentc_crypto_utils::cryptomat::{SignKCryptoWrapper, VerifyKFromUserKeyWrapper}; 5 | use sentc_crypto_utils::error::SdkUtilError; 6 | 7 | use crate::core::sign::{Signature, VerifyKey as CoreVk}; 8 | use crate::util::export::import_verify_key_from_pem_with_alg; 9 | use crate::util::{SignKey, VerifyKey}; 10 | 11 | impl SignKCryptoWrapper for SignKey 12 | { 13 | fn sign_with_head(&self, data: &[u8]) -> Result<(SignHead, Vec), SdkUtilError> 14 | { 15 | let sig = self.key.sign(data)?; 16 | 17 | Ok(( 18 | SignHead { 19 | id: self.key_id.clone(), 20 | alg: self.key.get_alg_str().to_string(), 21 | }, 22 | sig, 23 | )) 24 | } 25 | } 26 | 27 | impl VerifyKFromUserKeyWrapper for VerifyKey 28 | { 29 | type CoreVk = CoreVk; 30 | 31 | fn split_sig_and_data<'a>(alg: &str, data_with_sign: &'a [u8]) -> Result<(&'a [u8], &'a [u8]), SdkUtilError> 32 | { 33 | Ok(Signature::split_sig_and_data(alg, data_with_sign)?) 34 | } 35 | 36 | fn from_user_key(verify_key: &UserVerifyKeyData) -> Result 37 | { 38 | import_verify_key_from_pem_with_alg(&verify_key.verify_key_pem, &verify_key.verify_key_alg) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/util/crypto/sortable.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | 3 | use sentc_crypto_common::content_sortable::SortableEncryptOutput; 4 | use sentc_crypto_core::cryptomat::{CryptoAlg, SortableKey as CS}; 5 | use sentc_crypto_utils::cryptomat::SortableKeyWrapper; 6 | use sentc_crypto_utils::error::SdkUtilError; 7 | use sentc_crypto_utils::sortable_composer; 8 | 9 | use crate::core::sortable::OpeSortableKey; 10 | use crate::util::crypto::SortableKey; 11 | 12 | sortable_composer!(SortableKey, OpeSortableKey); 13 | 14 | impl SortableKeyWrapper for SortableKey 15 | { 16 | type Inner = OpeSortableKey; 17 | 18 | fn get_id(&self) -> &str 19 | { 20 | &self.key_id 21 | } 22 | 23 | fn get_key(&self) -> &Self::Inner 24 | { 25 | &self.key 26 | } 27 | 28 | fn encrypt_raw_string(&self, data: &str, max_len: Option) -> Result 29 | { 30 | let n = Self::prepare_string(data, max_len.unwrap_or(4)); 31 | 32 | Ok(self.key.encrypt_sortable(n)?) 33 | } 34 | 35 | fn encrypt_string(&self, data: &str, max_len: Option) -> Result 36 | { 37 | let number = self.encrypt_raw_string(data, max_len)?; 38 | 39 | Ok(SortableEncryptOutput { 40 | number, 41 | alg: self.key.get_alg_str().to_string(), 42 | key_id: self.key_id.clone(), 43 | }) 44 | } 45 | } 46 | 47 | impl SortableKey 48 | { 49 | fn transform_string_to_number(s: &str) -> u64 50 | { 51 | let mut number: u64 = 0; 52 | 53 | for c in s.chars() { 54 | let ascii_value = c as u64; 55 | number = number * 256 + ascii_value; 56 | } 57 | 58 | number / (u16::max_value() as u64 - 1) 59 | } 60 | 61 | fn prepare_string(data: &str, max_len: usize) -> u64 62 | { 63 | match data.len().cmp(&max_len) { 64 | Ordering::Greater => Self::transform_string_to_number(&data[..max_len]), 65 | Ordering::Less => { 66 | //fill it with dummy chars to get the len 67 | let mut st = data.to_string(); 68 | 69 | for _i in data.len()..max_len { 70 | st += "*"; 71 | } 72 | 73 | Self::transform_string_to_number(&st) 74 | }, 75 | Ordering::Equal => Self::transform_string_to_number(data), 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/util/crypto/symmetric_key.rs: -------------------------------------------------------------------------------- 1 | use openssl::base64::{decode_block, encode_block}; 2 | use sentc_crypto_common::crypto::EncryptedHead; 3 | use sentc_crypto_common::user::UserVerifyKeyData; 4 | use sentc_crypto_core::cryptomat::SymKey; 5 | use sentc_crypto_utils::cryptomat::{SignKWrapper, SymKeyCrypto}; 6 | use sentc_crypto_utils::error::SdkUtilError; 7 | 8 | use crate::util::{SymmetricKey, VerifyKey}; 9 | 10 | impl SymKeyCrypto for SymmetricKey 11 | { 12 | type VerifyKey = VerifyKey; 13 | 14 | fn encrypt_raw(&self, data: &[u8]) -> Result<(EncryptedHead, Vec), SdkUtilError> 15 | { 16 | let encrypted = self.key.encrypt(data)?; 17 | 18 | Ok(( 19 | EncryptedHead { 20 | id: self.key_id.to_string(), 21 | sign: None, 22 | }, 23 | encrypted, 24 | )) 25 | } 26 | 27 | fn encrypt_raw_with_sign(&self, data: &[u8], sign_key: &impl SignKWrapper) -> Result<(EncryptedHead, Vec), SdkUtilError> 28 | { 29 | let encrypted = self.key.encrypt(data)?; 30 | 31 | let (sign_head, data_with_sign) = sign_key.sign_with_head(&encrypted)?; 32 | 33 | Ok(( 34 | EncryptedHead { 35 | id: self.key_id.to_string(), 36 | sign: Some(sign_head), 37 | }, 38 | data_with_sign, 39 | )) 40 | } 41 | 42 | fn encrypt_raw_with_aad(&self, data: &[u8], aad: &[u8]) -> Result<(EncryptedHead, Vec), SdkUtilError> 43 | { 44 | let encrypted = self.key.encrypt_with_aad(data, aad)?; 45 | 46 | Ok(( 47 | EncryptedHead { 48 | id: self.key_id.to_string(), 49 | sign: None, 50 | }, 51 | encrypted, 52 | )) 53 | } 54 | 55 | fn encrypt_raw_with_aad_with_sign(&self, data: &[u8], aad: &[u8], sign_key: &impl SignKWrapper) 56 | -> Result<(EncryptedHead, Vec), SdkUtilError> 57 | { 58 | let encrypted = self.key.encrypt_with_aad(data, aad)?; 59 | 60 | let (sign_head, data_with_sign) = sign_key.sign_with_head(&encrypted)?; 61 | 62 | Ok(( 63 | EncryptedHead { 64 | id: self.key_id.to_string(), 65 | sign: Some(sign_head), 66 | }, 67 | data_with_sign, 68 | )) 69 | } 70 | 71 | fn decrypt_raw(&self, encrypted_data: &[u8], head: &EncryptedHead, verify_key: Option<&UserVerifyKeyData>) -> Result, SdkUtilError> 72 | { 73 | let data_to_decrypt = Self::prepare_decrypt(encrypted_data, head, verify_key)?; 74 | 75 | Ok(self.key.decrypt(data_to_decrypt)?) 76 | } 77 | 78 | fn decrypt_raw_with_aad( 79 | &self, 80 | encrypted_data: &[u8], 81 | aad: &[u8], 82 | head: &EncryptedHead, 83 | verify_key: Option<&UserVerifyKeyData>, 84 | ) -> Result, SdkUtilError> 85 | { 86 | let data_to_decrypt = Self::prepare_decrypt(encrypted_data, head, verify_key)?; 87 | 88 | Ok(self.key.decrypt_with_aad(data_to_decrypt, aad)?) 89 | } 90 | 91 | fn encrypt_string(&self, data: &str) -> Result 92 | { 93 | let encrypted = self.encrypt(data.as_bytes())?; 94 | 95 | Ok(encode_block(&encrypted)) 96 | } 97 | 98 | fn encrypt_string_with_sign(&self, data: &str, sign_key: &impl SignKWrapper) -> Result 99 | { 100 | let encrypted = self.encrypt_with_sign(data.as_bytes(), sign_key)?; 101 | 102 | Ok(encode_block(&encrypted)) 103 | } 104 | 105 | fn encrypt_string_with_aad(&self, data: &str, aad: &str) -> Result 106 | { 107 | let encrypted = self.encrypt_with_aad(data.as_bytes(), aad.as_bytes())?; 108 | 109 | Ok(encode_block(&encrypted)) 110 | } 111 | 112 | fn encrypt_string_with_aad_with_sign(&self, data: &str, aad: &str, sign_key: &impl SignKWrapper) -> Result 113 | { 114 | let encrypted = self.encrypt_with_aad_with_sign(data.as_bytes(), aad.as_bytes(), sign_key)?; 115 | 116 | Ok(encode_block(&encrypted)) 117 | } 118 | 119 | fn decrypt_string(&self, encrypted_data_with_head: &str, verify_key: Option<&UserVerifyKeyData>) -> Result 120 | { 121 | let encrypted = decode_block(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 122 | 123 | let decrypted = self.decrypt(&encrypted, verify_key)?; 124 | 125 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 126 | } 127 | 128 | fn decrypt_string_with_aad( 129 | &self, 130 | encrypted_data_with_head: &str, 131 | aad: &str, 132 | verify_key: Option<&UserVerifyKeyData>, 133 | ) -> Result 134 | { 135 | let encrypted = decode_block(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 136 | 137 | let decrypted = self.decrypt_with_aad(&encrypted, aad.as_bytes(), verify_key)?; 138 | 139 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /crypto_keys/crypto_rec_keys/src/util/export.rs: -------------------------------------------------------------------------------- 1 | use openssl::base64::{decode_block, encode_block}; 2 | use sentc_crypto_utils::error::SdkUtilError; 3 | use sentc_crypto_utils::{export_key_to_pem, import_key_from_pem}; 4 | 5 | use crate::core::asym::{PublicKey, ECIES_ML_KEM_REC_HYBRID_OUTPUT, ECIES_REC_OUTPUT, ML_KEM_REC_OUTPUT}; 6 | use crate::core::sign::{Signature, VerifyKey, ED25519_ML_DSA_HYBRID_REC_OUTPUT, FIPS_OPENSSL_ED25519, ML_DSA_REC_OUTPUT}; 7 | use crate::util::HybridPublicKeyExportFormat; 8 | 9 | pub fn import_public_key_from_pem_with_alg(public_key: &str, alg: &str) -> Result 10 | { 11 | match alg { 12 | ECIES_REC_OUTPUT => { 13 | let bytes = import_key_from_pem(public_key)?; 14 | Ok(PublicKey::ecies_from_bytes_owned(bytes)?) 15 | }, 16 | ML_KEM_REC_OUTPUT => { 17 | let bytes = import_key_from_pem(public_key)?; 18 | Ok(PublicKey::ml_kem_from_bytes_owned(bytes)) 19 | }, 20 | ECIES_ML_KEM_REC_HYBRID_OUTPUT => { 21 | let key: HybridPublicKeyExportFormat = serde_json::from_str(public_key).map_err(SdkUtilError::JsonParseFailed)?; 22 | 23 | let bytes_x = import_key_from_pem(&key.x)?; 24 | let bytes_k = import_key_from_pem(&key.k)?; 25 | 26 | Ok(PublicKey::ecies_ml_kem_hybrid_from_bytes_owned(bytes_x, bytes_k)?) 27 | }, 28 | _ => Err(SdkUtilError::AlgNotFound), 29 | } 30 | } 31 | 32 | pub fn import_verify_key_from_pem_with_alg(verify_key: &str, alg: &str) -> Result 33 | { 34 | match alg { 35 | FIPS_OPENSSL_ED25519 => { 36 | let bytes = import_key_from_pem(verify_key)?; 37 | Ok(VerifyKey::ed25519_from_bytes_owned(bytes)?) 38 | }, 39 | ML_DSA_REC_OUTPUT => { 40 | let bytes = import_key_from_pem(verify_key)?; 41 | Ok(VerifyKey::ml_dsa_from_bytes_owned(bytes)) 42 | }, 43 | ED25519_ML_DSA_HYBRID_REC_OUTPUT => { 44 | let key: HybridPublicKeyExportFormat = serde_json::from_str(verify_key).map_err(SdkUtilError::JsonParseFailed)?; 45 | 46 | let bytes_x = import_key_from_pem(&key.x)?; 47 | let bytes_k = import_key_from_pem(&key.k)?; 48 | 49 | Ok(VerifyKey::ed25519_ml_dsa_hybrid_from_bytes_owned(bytes_x, bytes_k)?) 50 | }, 51 | _ => Err(SdkUtilError::AlgNotFound), 52 | } 53 | } 54 | 55 | pub fn import_sig_from_string(sig: &str, alg: &str) -> Result 56 | { 57 | match alg { 58 | FIPS_OPENSSL_ED25519 => { 59 | let bytes = decode_block(sig).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 60 | Ok(Signature::ed25519_from_bytes_owned(bytes)) 61 | }, 62 | ML_DSA_REC_OUTPUT => { 63 | let bytes = decode_block(sig).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 64 | Ok(Signature::ml_dsa_from_bytes_owned(bytes)) 65 | }, 66 | ED25519_ML_DSA_HYBRID_REC_OUTPUT => { 67 | let key: HybridPublicKeyExportFormat = serde_json::from_str(sig).map_err(SdkUtilError::JsonParseFailed)?; 68 | 69 | let bytes_x = decode_block(&key.x).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 70 | let bytes_k = decode_block(&key.k).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 71 | 72 | Ok(Signature::ed25519_ml_dsa_hybrid_from_bytes_owned(bytes_x, bytes_k)) 73 | }, 74 | _ => Err(SdkUtilError::AlgNotFound), 75 | } 76 | } 77 | 78 | pub fn sig_to_string(sig: &Signature) -> String 79 | { 80 | match sig { 81 | Signature::Ed25519(s) => encode_block(s.as_ref()), 82 | Signature::MlDsa(s) => encode_block(s.as_ref()), 83 | Signature::Ed25519MlDsaHybrid(s) => { 84 | let (x, k) = s.get_raw_sig(); 85 | 86 | let x = encode_block(x); 87 | let k = encode_block(k); 88 | 89 | serde_json::to_string(&HybridPublicKeyExportFormat { 90 | x, 91 | k, 92 | }) 93 | .unwrap() 94 | }, 95 | } 96 | } 97 | 98 | pub fn export_raw_public_key_to_pem(key: &PublicKey) -> Result 99 | { 100 | match key { 101 | PublicKey::Ecies(key) => export_key_to_pem(&key.export()?), 102 | PublicKey::MlKem(key) => export_key_to_pem(key.as_ref()), 103 | PublicKey::EciesMlKemHybrid(key) => { 104 | let (x, k) = key.prepare_export()?; 105 | 106 | let x = export_key_to_pem(&x)?; 107 | let k = export_key_to_pem(k)?; 108 | 109 | serde_json::to_string(&HybridPublicKeyExportFormat { 110 | x, 111 | k, 112 | }) 113 | .map_err(|_| SdkUtilError::JsonToStringFailed) 114 | }, 115 | } 116 | } 117 | 118 | pub fn export_raw_verify_key_to_pem(key: &VerifyKey) -> Result 119 | { 120 | match key { 121 | VerifyKey::Ed25519(key) => export_key_to_pem(&key.export()?), 122 | VerifyKey::MlDsa(key) => export_key_to_pem(key.as_ref()), 123 | VerifyKey::Ed25519MlDsaHybrid(key) => { 124 | let (x, k) = key.prepare_export()?; 125 | 126 | let x = export_key_to_pem(&x)?; 127 | let k = export_key_to_pem(k)?; 128 | 129 | serde_json::to_string(&HybridPublicKeyExportFormat { 130 | x, 131 | k, 132 | }) 133 | .map_err(|_| SdkUtilError::JsonToStringFailed) 134 | }, 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc-crypto-std-keys" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | authors.workspace = true 7 | homepage.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | description = "Key impl of the classic algorithms that were used pre 0.14.0 of sentc." 13 | 14 | include = [ 15 | "Cargo.toml", 16 | "../LICENSE", 17 | "src/**/*", 18 | ] 19 | 20 | [dependencies] 21 | sentc-crypto-core.workspace = true 22 | sentc-crypto-utils = { workspace = true, optional = true } 23 | sentc-crypto-common = { workspace = true, optional = true } 24 | 25 | aes-gcm = "0.9.4" 26 | x25519-dalek = { version = "2.0.1", default-features = false, features = ["static_secrets"] } 27 | ed25519-dalek = { version = "2.1.1", default-features = false, features = ["fast", "rand_core"] } 28 | rand_core = { version = "0.6.3", default-features = false, features = ["getrandom"] } 29 | sha2 = { version = "0.10.2", default-features = false } 30 | hkdf = { version = "0.12.3", default-features = false } 31 | hmac = "0.12.1" 32 | argon2 = "0.3" 33 | ope = "0.1.1" 34 | pqc_kyber_edit = { version = "0.7.2", features = ["90s-fixslice"] } 35 | pqc_dilithium_edit = { version = "0.2.0", features = ["mode3", "aes", "random_signing"] } 36 | 37 | # key and data export 38 | base64ct = { workspace = true, optional = true } # must use this version because it is not comp. with password_hash from argon2 39 | serde_json = { workspace = true, optional = true } 40 | serde = { workspace = true, optional = true } 41 | 42 | [features] 43 | default = ["aes", "ecies_kyber_hybrid", "ed25519_dilithium_hybrid", "hmac_sha256", "ope_sort", "argon2_hash", "default_env"] 44 | 45 | # symmetric encryption 46 | aes = [] 47 | 48 | # asymmetric encryption 49 | ecies = [] 50 | ecies_kyber_hybrid = [] 51 | 52 | # sign 53 | ed25519 = [] 54 | ed25519_dilithium_hybrid = [] 55 | 56 | # searchable 57 | hmac_sha256 = [] 58 | 59 | # sortable 60 | ope_sort = [] 61 | 62 | #pw hash 63 | argon2_hash = [] 64 | 65 | # Descibe the used env for the crng 66 | default_env = [] 67 | 68 | wrapper = ["sentc-crypto-utils", "base64ct", "serde", "serde_json", "sentc-crypto-common"] 69 | full = ["wrapper", "sentc-crypto-utils/encryption"] -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/core/asym/mod.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use sentc_crypto_core::cryptomat::{CryptoAlg, Pk, SignK, Sk, SkComposer, StaticKeyPair, SymKey, VerifyK}; 4 | use sentc_crypto_core::Error; 5 | 6 | use crate::core::asym::ecies::{EciesPk, EciesSk}; 7 | use crate::core::asym::ecies_kyber_hybrid::{EciesKyberHybridPk, EciesKyberHybridSk}; 8 | use crate::core::asym::pqc_kyber::{KyberPk, KyberSk}; 9 | 10 | pub(crate) mod ecies; 11 | pub(crate) mod ecies_kyber_hybrid; 12 | pub(crate) mod pqc_kyber; 13 | 14 | macro_rules! deref_macro { 15 | ($self:expr, $method:ident $(, $args:expr)*) => { 16 | match $self { 17 | Self::Ecies(inner) => inner.$method($($args),*), 18 | Self::Kyber(inner) => inner.$method($($args),*), 19 | Self::EciesKyberHybrid(inner) => inner.$method($($args),*), 20 | } 21 | }; 22 | } 23 | 24 | macro_rules! crypto_alg_impl { 25 | ($name:ty) => { 26 | impl CryptoAlg for $name 27 | { 28 | fn get_alg_str(&self) -> &'static str 29 | { 30 | deref_macro!(self, get_alg_str) 31 | } 32 | } 33 | }; 34 | } 35 | 36 | macro_rules! get_inner_key { 37 | ($st:ty,$t:ident) => { 38 | impl $st 39 | { 40 | pub fn ecies_from_bytes_owned(bytes: Vec) -> Result 41 | { 42 | Ok(Self::Ecies(bytes.try_into()?)) 43 | } 44 | 45 | pub fn kyber_from_bytes_owned(bytes: Vec) -> Result 46 | { 47 | Ok(Self::Kyber(bytes.try_into()?)) 48 | } 49 | 50 | pub fn ecies_kyber_hybrid_from_bytes_owned(bytes_x: Vec, bytes_k: Vec) -> Result 51 | { 52 | Ok(Self::EciesKyberHybrid($t::from_bytes_owned(bytes_x, bytes_k)?)) 53 | } 54 | } 55 | }; 56 | } 57 | 58 | #[derive(Clone)] 59 | pub enum PublicKey 60 | { 61 | Ecies(EciesPk), 62 | Kyber(KyberPk), 63 | EciesKyberHybrid(EciesKyberHybridPk), 64 | } 65 | 66 | get_inner_key!(PublicKey, EciesKyberHybridPk); 67 | crypto_alg_impl!(PublicKey); 68 | 69 | impl Pk for PublicKey 70 | { 71 | fn sign_public_key(&self, sign_key: &S) -> Result 72 | { 73 | let out = match self { 74 | PublicKey::Ecies(k) => k.sign_public_key(sign_key)?, 75 | PublicKey::Kyber(k) => k.sign_public_key(sign_key)?, 76 | PublicKey::EciesKyberHybrid(k) => k.sign_public_key(sign_key)?, 77 | }; 78 | 79 | Ok(out) 80 | } 81 | 82 | fn verify_public_key(&self, verify_key: &V, sig: &V::Signature) -> Result 83 | { 84 | deref_macro!(self, verify_public_key, verify_key, sig) 85 | } 86 | 87 | fn encrypt(&self, data: &[u8]) -> Result, Error> 88 | { 89 | deref_macro!(self, encrypt, data) 90 | } 91 | } 92 | 93 | pub enum SecretKey 94 | { 95 | Ecies(EciesSk), 96 | Kyber(KyberSk), 97 | EciesKyberHybrid(EciesKyberHybridSk), 98 | } 99 | 100 | get_inner_key!(SecretKey, EciesKyberHybridSk); 101 | crypto_alg_impl!(SecretKey); 102 | 103 | impl Sk for SecretKey 104 | { 105 | fn encrypt_by_master_key(&self, master_key: &M) -> Result, Error> 106 | { 107 | deref_macro!(self, encrypt_by_master_key, master_key) 108 | } 109 | 110 | fn decrypt(&self, ciphertext: &[u8]) -> Result, Error> 111 | { 112 | deref_macro!(self, decrypt, ciphertext) 113 | } 114 | } 115 | 116 | impl SkComposer for SecretKey 117 | { 118 | type SecretKey = Self; 119 | 120 | fn decrypt_by_master_key(master_key: &M, encrypted_key: &[u8], alg_str: &str) -> Result 121 | { 122 | let decrypted_bytes = master_key.decrypt(encrypted_key)?; 123 | 124 | let key = match alg_str { 125 | ecies::ECIES_OUTPUT => Self::Ecies(decrypted_bytes.try_into()?), 126 | pqc_kyber::KYBER_OUTPUT => Self::Kyber(decrypted_bytes.try_into()?), 127 | ecies_kyber_hybrid::ECIES_KYBER_HYBRID_OUTPUT => Self::EciesKyberHybrid(decrypted_bytes.try_into()?), 128 | _ => return Err(Error::AlgNotFound), 129 | }; 130 | 131 | Ok(key) 132 | } 133 | } 134 | 135 | impl StaticKeyPair for SecretKey 136 | { 137 | type SecretKey = Self; 138 | type PublicKey = PublicKey; 139 | 140 | fn generate_static_keypair() -> Result<(Self::SecretKey, Self::PublicKey), Error> 141 | { 142 | #[cfg(feature = "ecies_kyber_hybrid")] 143 | let (sk, pk) = ecies_kyber_hybrid::EciesKyberHybridKeyPair::generate_static_keypair()?; 144 | 145 | #[cfg(feature = "ecies")] 146 | let (sk, pk) = ecies::EciesKeyPair::generate_static_keypair()?; 147 | 148 | Ok((sk.into(), pk.into())) 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/core/hmac/hmac_sha256.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use hmac::{Hmac, Mac}; 4 | use sentc_crypto_core::cryptomat::{SearchableKey, SearchableKeyGen, SymKey}; 5 | use sentc_crypto_core::{as_ref_bytes_single_value, crypto_alg_str_impl, try_from_bytes_owned_single_value, Error}; 6 | use sha2::Sha256; 7 | 8 | use crate::core::hmac::HmacKey; 9 | use crate::core::sym; 10 | use crate::core::sym::aes_gcm::AesKey; 11 | 12 | pub const HMAC_SHA256_OUTPUT: &str = "HMAC-SHA256"; 13 | 14 | type HmacSha256 = Hmac; 15 | 16 | pub struct HmacSha256Key(AesKey); 17 | 18 | try_from_bytes_owned_single_value!(HmacSha256Key); 19 | as_ref_bytes_single_value!(HmacSha256Key); 20 | crypto_alg_str_impl!(HmacSha256Key, HMAC_SHA256_OUTPUT); 21 | 22 | impl Into for HmacSha256Key 23 | { 24 | fn into(self) -> HmacKey 25 | { 26 | HmacKey::HmacSha256(self) 27 | } 28 | } 29 | 30 | impl SearchableKey for HmacSha256Key 31 | { 32 | fn encrypt_key_with_master_key(&self, master_key: &M) -> Result, Error> 33 | { 34 | master_key.encrypt(&self.0) 35 | } 36 | 37 | fn encrypt_searchable(&self, data: &[u8]) -> Result, Error> 38 | { 39 | let mut mac = HmacSha256::new_from_slice(&self.0).map_err(|_| Error::HmacAuthFailedLength)?; 40 | 41 | mac.update(data); 42 | 43 | let result = mac.finalize(); 44 | let result = result.into_bytes(); 45 | 46 | Ok(result.to_vec()) 47 | } 48 | 49 | fn verify_encrypted_searchable(&self, data: &[u8], check: &[u8]) -> Result 50 | { 51 | let mut mac = HmacSha256::new_from_slice(&self.0).map_err(|_| Error::HmacAuthFailedLength)?; 52 | 53 | mac.update(data); 54 | 55 | Ok(mac.verify_slice(check).is_ok()) 56 | } 57 | } 58 | 59 | impl SearchableKeyGen for HmacSha256Key 60 | { 61 | type SearchableKey = Self; 62 | 63 | fn generate() -> Result 64 | { 65 | Ok(Self(sym::aes_gcm::raw_generate()?)) 66 | } 67 | } 68 | 69 | #[cfg(test)] 70 | mod test 71 | { 72 | use super::*; 73 | 74 | #[test] 75 | fn test_create_hmac_key() 76 | { 77 | let _ = HmacSha256Key::generate().unwrap(); 78 | } 79 | 80 | #[test] 81 | fn test_plain_auth_msg() 82 | { 83 | let msg = "Hello world üöäéèßê°"; 84 | 85 | let out = HmacSha256Key::generate().unwrap(); 86 | 87 | let mac = out.encrypt_searchable(msg.as_bytes()).unwrap(); 88 | 89 | let verify = out 90 | .verify_encrypted_searchable(msg.as_bytes(), &mac) 91 | .unwrap(); 92 | 93 | assert!(verify); 94 | } 95 | 96 | #[test] 97 | fn test_not_verify_with_wrong_key() 98 | { 99 | let msg = "Hello world üöäéèßê°"; 100 | 101 | let out = HmacSha256Key::generate().unwrap(); 102 | let out2 = HmacSha256Key::generate().unwrap(); 103 | 104 | let mac = out.encrypt_searchable(msg.as_bytes()).unwrap(); 105 | 106 | let verify = out2 107 | .verify_encrypted_searchable(msg.as_bytes(), &mac) 108 | .unwrap(); 109 | 110 | assert!(!verify); 111 | } 112 | 113 | #[test] 114 | fn test_not_producing_the_same_output_with_different_keys() 115 | { 116 | let msg = "Hello world üöäéèßê°"; 117 | 118 | let out = HmacSha256Key::generate().unwrap(); 119 | let out2 = HmacSha256Key::generate().unwrap(); 120 | 121 | let mac1 = out.encrypt_searchable(msg.as_bytes()).unwrap(); 122 | 123 | let mac2 = out2.encrypt_searchable(msg.as_bytes()).unwrap(); 124 | 125 | assert_ne!(mac1, mac2); 126 | } 127 | 128 | #[test] 129 | fn test_producing_the_same_output_with_same_keys() 130 | { 131 | let msg = "Hello world üöäéèßê°"; 132 | 133 | let out = HmacSha256Key::generate().unwrap(); 134 | 135 | let mac1 = out.encrypt_searchable(msg.as_bytes()).unwrap(); 136 | 137 | let mac2 = out.encrypt_searchable(msg.as_bytes()).unwrap(); 138 | 139 | assert_eq!(mac1, mac2); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/core/hmac/mod.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use sentc_crypto_core::cryptomat::{CryptoAlg, SearchableKey, SearchableKeyComposer, SearchableKeyGen, SymKey}; 4 | use sentc_crypto_core::Error; 5 | 6 | use crate::core::hmac::hmac_sha256::HmacSha256Key; 7 | 8 | pub(crate) mod hmac_sha256; 9 | 10 | macro_rules! deref_macro { 11 | ($self:expr, $method:ident $(, $args:expr)*) => { 12 | match $self { 13 | Self::HmacSha256(inner) => inner.$method($($args),*), 14 | } 15 | }; 16 | } 17 | 18 | pub enum HmacKey 19 | { 20 | HmacSha256(HmacSha256Key), 21 | } 22 | 23 | impl HmacKey 24 | { 25 | pub fn hmac_sha256_from_bytes_owned(bytes: Vec) -> Result 26 | { 27 | Ok(HmacKey::HmacSha256(bytes.try_into()?)) 28 | } 29 | } 30 | 31 | impl CryptoAlg for HmacKey 32 | { 33 | fn get_alg_str(&self) -> &'static str 34 | { 35 | deref_macro!(self, get_alg_str) 36 | } 37 | } 38 | 39 | impl AsRef<[u8]> for HmacKey 40 | { 41 | fn as_ref(&self) -> &[u8] 42 | { 43 | deref_macro!(self, as_ref) 44 | } 45 | } 46 | 47 | impl SearchableKey for HmacKey 48 | { 49 | fn encrypt_key_with_master_key(&self, master_key: &M) -> Result, Error> 50 | { 51 | deref_macro!(self, encrypt_key_with_master_key, master_key) 52 | } 53 | 54 | fn encrypt_searchable(&self, data: &[u8]) -> Result, Error> 55 | { 56 | deref_macro!(self, encrypt_searchable, data) 57 | } 58 | 59 | fn verify_encrypted_searchable(&self, data: &[u8], check: &[u8]) -> Result 60 | { 61 | deref_macro!(self, verify_encrypted_searchable, data, check) 62 | } 63 | } 64 | 65 | impl SearchableKeyGen for HmacKey 66 | { 67 | type SearchableKey = Self; 68 | 69 | fn generate() -> Result 70 | { 71 | #[cfg(feature = "hmac_sha256")] 72 | Ok(HmacSha256Key::generate()?.into()) 73 | } 74 | } 75 | 76 | impl SearchableKeyComposer for HmacKey 77 | { 78 | type Key = Self; 79 | 80 | fn decrypt_by_master_key(master_key: &M, encrypted_key: &[u8], alg_str: &str) -> Result 81 | { 82 | let key = master_key.decrypt(encrypted_key)?; 83 | 84 | match alg_str { 85 | hmac_sha256::HMAC_SHA256_OUTPUT => Ok(HmacKey::HmacSha256(key.try_into()?)), 86 | _ => Err(Error::AlgNotFound), 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/core/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod asym; 2 | pub(crate) mod hmac; 3 | pub(crate) mod pw_hash; 4 | pub(crate) mod sign; 5 | pub(crate) mod sortable; 6 | pub(crate) mod sym; 7 | 8 | pub use self::asym::ecies::{EciesKeyPair, EciesPk, EciesSk, ECIES_OUTPUT}; 9 | pub use self::asym::ecies_kyber_hybrid::{EciesKyberHybridKeyPair, EciesKyberHybridPk, EciesKyberHybridSk, ECIES_KYBER_HYBRID_OUTPUT}; 10 | pub use self::asym::pqc_kyber::{KyberKeyPair, KyberPk, KyberSk, KYBER_OUTPUT}; 11 | pub use self::asym::{PublicKey, SecretKey}; 12 | pub use self::hmac::hmac_sha256::{HmacSha256Key, HMAC_SHA256_OUTPUT}; 13 | pub use self::hmac::HmacKey; 14 | pub use self::pw_hash::argon2::ARGON_2_OUTPUT; 15 | pub use self::pw_hash::{ 16 | ClientRandomValue, 17 | DeriveAuthKeyForAuth, 18 | DeriveMasterKeyForAuth, 19 | HashedAuthenticationKey, 20 | PasswordEncryptSalt, 21 | PwHasherGetter, 22 | }; 23 | pub use self::sign::ed25519::{Ed25519KeyPair, Ed25519Sig, Ed25519SignK, Ed25519VerifyK, ED25519_OUTPUT}; 24 | pub use self::sign::ed25519_dilithium_hybrid::{ 25 | Ed25519DilithiumHybridKeyPair, 26 | Ed25519DilithiumHybridSig, 27 | Ed25519DilithiumHybridSignK, 28 | Ed25519DilithiumHybridVerifyKey, 29 | ED25519_DILITHIUM_HYBRID_OUTPUT, 30 | }; 31 | pub use self::sign::pqc_dilithium::DILITHIUM_OUTPUT; 32 | pub use self::sign::{SignKey, Signature, VerifyKey}; 33 | pub use self::sortable::SortKeys; 34 | pub use self::sym::aes_gcm::{Aes256GcmKey, AES_GCM_OUTPUT}; 35 | pub use self::sym::SymmetricKey; 36 | 37 | #[macro_export] 38 | macro_rules! hybrid_key_import_export { 39 | ($st:ty) => { 40 | impl $st 41 | { 42 | pub fn get_raw_keys(&self) -> (&[u8], &[u8]) 43 | { 44 | (&self.x, &self.k) 45 | } 46 | 47 | pub fn from_bytes_owned(bytes_x: Vec, bytes_k: Vec) -> Result 48 | { 49 | Ok(Self { 50 | x: bytes_x 51 | .try_into() 52 | .map_err(|_| sentc_crypto_core::Error::KeyDecryptFailed)?, 53 | k: bytes_k 54 | .try_into() 55 | .map_err(|_| sentc_crypto_core::Error::KeyDecryptFailed)?, 56 | }) 57 | } 58 | } 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/core/sortable/mod.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use sentc_crypto_core::cryptomat::{CryptoAlg, SortableKey, SortableKeyComposer, SortableKeyGen, SymKey}; 4 | use sentc_crypto_core::Error; 5 | 6 | use crate::core::sortable::ope::OpeSortableKey; 7 | 8 | pub(crate) mod ope; 9 | 10 | macro_rules! deref_macro { 11 | ($self:expr, $method:ident $(, $args:expr)*) => { 12 | match $self { 13 | Self::Ope(inner) => inner.$method($($args),*), 14 | } 15 | }; 16 | } 17 | 18 | pub enum SortKeys 19 | { 20 | Ope(OpeSortableKey), 21 | } 22 | 23 | impl SortKeys 24 | { 25 | pub fn ope_key_from_bytes_owned(bytes: Vec) -> Result 26 | { 27 | Ok(SortKeys::Ope(bytes.try_into()?)) 28 | } 29 | } 30 | 31 | impl CryptoAlg for SortKeys 32 | { 33 | fn get_alg_str(&self) -> &'static str 34 | { 35 | deref_macro!(self, get_alg_str) 36 | } 37 | } 38 | 39 | impl AsRef<[u8]> for SortKeys 40 | { 41 | fn as_ref(&self) -> &[u8] 42 | { 43 | deref_macro!(self, as_ref) 44 | } 45 | } 46 | 47 | impl SortableKey for SortKeys 48 | { 49 | fn encrypt_key_with_master_key(&self, master_key: &M) -> Result, Error> 50 | { 51 | deref_macro!(self, encrypt_key_with_master_key, master_key) 52 | } 53 | 54 | fn encrypt_sortable(&self, data: u64) -> Result 55 | { 56 | deref_macro!(self, encrypt_sortable, data) 57 | } 58 | } 59 | 60 | impl SortableKeyGen for SortKeys 61 | { 62 | type SortableKey = Self; 63 | 64 | fn generate() -> Result 65 | { 66 | #[cfg(feature = "ope_sort")] 67 | Ok(OpeSortableKey::generate()?.into()) 68 | } 69 | } 70 | 71 | impl SortableKeyComposer for SortKeys 72 | { 73 | type Key = Self; 74 | 75 | fn decrypt_by_master_key(master_key: &M, encrypted_key: &[u8], alg_str: &str) -> Result 76 | { 77 | let key = master_key.decrypt(encrypted_key)?; 78 | 79 | match alg_str { 80 | ope::OPE_OUT => Ok(SortKeys::Ope(key.try_into()?)), 81 | _ => Err(Error::AlgNotFound), 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/core/sortable/ope.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use ope::{get_ope, OpeError, OpeKey}; 4 | use rand_core::{CryptoRng, RngCore}; 5 | use sentc_crypto_core::cryptomat::{SortableKey, SortableKeyGen, SymKey}; 6 | use sentc_crypto_core::{as_ref_bytes_single_value, crypto_alg_str_impl, try_from_bytes_owned_single_value, Error}; 7 | 8 | use crate::core::sortable::SortKeys; 9 | use crate::get_rand; 10 | 11 | pub const OPE_OUT: &str = "OPE-16"; 12 | 13 | pub struct OpeSortableKey(OpeKey); 14 | 15 | try_from_bytes_owned_single_value!(OpeSortableKey); 16 | as_ref_bytes_single_value!(OpeSortableKey); 17 | 18 | crypto_alg_str_impl!(OpeSortableKey, OPE_OUT); 19 | 20 | impl SortableKey for OpeSortableKey 21 | { 22 | fn encrypt_key_with_master_key(&self, master_key: &M) -> Result, Error> 23 | { 24 | master_key.encrypt(&self.0) 25 | } 26 | 27 | fn encrypt_sortable(&self, data: u64) -> Result 28 | { 29 | if data > 65532 { 30 | return Err(Error::OpeStringToLarge); 31 | } 32 | 33 | let ope = get_ope(&self.0); 34 | 35 | let out = ope.encrypt(data); 36 | 37 | match out { 38 | Ok(o) => Ok(o), 39 | Err(err) => { 40 | match err { 41 | OpeError::HdgInvalidInputs => Err(Error::OpeHdgInvalidInputs), 42 | OpeError::OpeRange => Err(Error::OpeRangeError), 43 | } 44 | }, 45 | } 46 | } 47 | } 48 | 49 | impl Into for OpeSortableKey 50 | { 51 | fn into(self) -> SortKeys 52 | { 53 | SortKeys::Ope(self) 54 | } 55 | } 56 | 57 | impl SortableKeyGen for OpeSortableKey 58 | { 59 | type SortableKey = Self; 60 | 61 | fn generate() -> Result 62 | { 63 | Ok(Self(generate_key_internally(&mut get_rand())?)) 64 | } 65 | } 66 | 67 | //__________________________________________________________________________________________________ 68 | 69 | fn generate_key_internally(rng: &mut R) -> Result 70 | { 71 | let mut key = [0u8; 16]; 72 | 73 | rng.try_fill_bytes(&mut key) 74 | .map_err(|_| Error::KeyCreationFailed)?; 75 | 76 | Ok(key) 77 | } 78 | 79 | #[cfg(test)] 80 | mod test 81 | { 82 | use super::*; 83 | 84 | #[test] 85 | fn test_gen_key() 86 | { 87 | let _ = OpeSortableKey::generate().unwrap(); 88 | } 89 | 90 | #[test] 91 | fn test_encrypt() 92 | { 93 | let key = OpeSortableKey::generate().unwrap(); 94 | 95 | let numbers = [262u64, 300, 1000, 65531]; 96 | 97 | let mut out = [0u64; 4]; 98 | 99 | for (i, number) in numbers.iter().enumerate() { 100 | out[i] = key.encrypt_sortable(*number).unwrap(); 101 | } 102 | 103 | //check 104 | 105 | let mut past_item = 0; 106 | 107 | for item in out { 108 | assert!(past_item < item); 109 | 110 | past_item = item; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/core/sym/mod.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use sentc_crypto_core::cryptomat::{CryptoAlg, SymKey, SymKeyComposer, SymKeyGen}; 4 | use sentc_crypto_core::Error; 5 | 6 | use crate::core::sym::aes_gcm::Aes256GcmKey; 7 | 8 | pub(crate) mod aes_gcm; 9 | 10 | macro_rules! deref_macro { 11 | ($self:expr, $method:ident $(, $args:expr)*) => { 12 | match $self { 13 | Self::Aes(inner) => inner.$method($($args),*), 14 | } 15 | }; 16 | } 17 | 18 | pub enum SymmetricKey 19 | { 20 | Aes(Aes256GcmKey), 21 | } 22 | 23 | impl SymmetricKey 24 | { 25 | pub fn aes_key_from_bytes_owned(bytes: Vec) -> Result 26 | { 27 | Ok(Self::Aes(bytes.try_into()?)) 28 | } 29 | } 30 | 31 | impl SymKeyComposer for SymmetricKey 32 | { 33 | type SymmetricKey = Self; 34 | 35 | fn from_bytes_owned(bytes: Vec, alg_str: &str) -> Result 36 | { 37 | match alg_str { 38 | aes_gcm::AES_GCM_OUTPUT => Ok(Self::Aes(bytes.try_into()?)), 39 | _ => Err(Error::AlgNotFound), 40 | } 41 | } 42 | } 43 | 44 | impl SymKeyGen for SymmetricKey 45 | { 46 | type SymmetricKey = Self; 47 | 48 | fn generate() -> Result 49 | { 50 | #[cfg(feature = "aes")] 51 | Ok(Aes256GcmKey::generate()?.into()) 52 | } 53 | } 54 | 55 | impl CryptoAlg for SymmetricKey 56 | { 57 | fn get_alg_str(&self) -> &'static str 58 | { 59 | deref_macro!(self, get_alg_str) 60 | } 61 | } 62 | 63 | impl AsRef<[u8]> for SymmetricKey 64 | { 65 | fn as_ref(&self) -> &[u8] 66 | { 67 | deref_macro!(self, as_ref) 68 | } 69 | } 70 | 71 | impl SymKey for SymmetricKey 72 | { 73 | fn encrypt(&self, data: &[u8]) -> Result, Error> 74 | { 75 | deref_macro!(self, encrypt, data) 76 | } 77 | 78 | fn decrypt(&self, ciphertext: &[u8]) -> Result, Error> 79 | { 80 | deref_macro!(self, decrypt, ciphertext) 81 | } 82 | 83 | fn encrypt_with_aad(&self, data: &[u8], aad: &[u8]) -> Result, Error> 84 | { 85 | deref_macro!(self, encrypt_with_aad, data, aad) 86 | } 87 | 88 | fn decrypt_with_aad(&self, ciphertext: &[u8], aad: &[u8]) -> Result, Error> 89 | { 90 | deref_macro!(self, decrypt_with_aad, ciphertext, aad) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![allow(clippy::infallible_destructuring_match, clippy::tabs_in_doc_comments, clippy::from_over_into)] 3 | 4 | extern crate alloc; 5 | 6 | use rand_core::{CryptoRng, OsRng, RngCore}; 7 | 8 | pub mod core; 9 | #[cfg(feature = "wrapper")] 10 | pub mod util; 11 | 12 | fn get_rand() -> impl CryptoRng + RngCore 13 | { 14 | #[cfg(feature = "default_env")] 15 | OsRng 16 | } 17 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/util/crypto/asym.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use base64ct::{Base64, Encoding}; 5 | use sentc_crypto_common::crypto::EncryptedHead; 6 | use sentc_crypto_common::user::{UserPublicKeyData, UserVerifyKeyData}; 7 | use sentc_crypto_core::cryptomat::Sk; 8 | use sentc_crypto_utils::cryptomat::{PkFromUserKeyWrapper, SignKWrapper, SkCryptoWrapper, VerifyKFromUserKeyWrapper}; 9 | use sentc_crypto_utils::error::SdkUtilError; 10 | 11 | use crate::core::{PublicKey as CorePk, Signature}; 12 | use crate::util::export::import_public_key_from_pem_with_alg; 13 | use crate::util::{PublicKey, SecretKey, VerifyKey}; 14 | 15 | impl PkFromUserKeyWrapper for PublicKey 16 | { 17 | type CorePk = CorePk; 18 | 19 | fn encrypt_string_with_user_key(reply_public_key: &UserPublicKeyData, data: &str) -> Result 20 | { 21 | let encrypted = Self::encrypt_with_user_key(reply_public_key, data.as_bytes())?; 22 | 23 | Ok(Base64::encode_string(&encrypted)) 24 | } 25 | 26 | fn encrypt_string_with_user_key_with_sign( 27 | reply_public_key: &UserPublicKeyData, 28 | data: &str, 29 | sign_key: &impl SignKWrapper, 30 | ) -> Result 31 | { 32 | let encrypted = Self::encrypt_with_user_key_with_sign(reply_public_key, data.as_bytes(), sign_key)?; 33 | 34 | Ok(Base64::encode_string(&encrypted)) 35 | } 36 | 37 | fn from_user_key(reply_public_key: &UserPublicKeyData) -> Result 38 | { 39 | import_public_key_from_pem_with_alg(&reply_public_key.public_key_pem, &reply_public_key.public_key_alg) 40 | } 41 | } 42 | 43 | impl SkCryptoWrapper for SecretKey 44 | { 45 | fn decrypt_raw(&self, encrypted_data: &[u8], head: &EncryptedHead, verify_key: Option<&UserVerifyKeyData>) -> Result, SdkUtilError> 46 | { 47 | match &head.sign { 48 | None => Ok(self.key.decrypt(encrypted_data)?), 49 | Some(h) => { 50 | match verify_key { 51 | None => { 52 | let (_, encrypted_data_without_sig) = Signature::split_sig_and_data(&h.alg, encrypted_data)?; 53 | Ok(self.key.decrypt(encrypted_data_without_sig)?) 54 | }, 55 | Some(vk) => { 56 | let encrypted_data_without_sig = VerifyKey::verify_with_user_key(vk, encrypted_data, h)?; 57 | Ok(self.key.decrypt(encrypted_data_without_sig)?) 58 | }, 59 | } 60 | }, 61 | } 62 | } 63 | 64 | fn decrypt_string(&self, encrypted_data_with_head: &str, verify_key: Option<&UserVerifyKeyData>) -> Result 65 | { 66 | let encrypted = Base64::decode_vec(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 67 | let decrypted = self.decrypt(&encrypted, verify_key)?; 68 | 69 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/util/crypto/mod.rs: -------------------------------------------------------------------------------- 1 | mod asym; 2 | mod searchable; 3 | mod sign; 4 | mod sortable; 5 | mod symmetric_key; 6 | 7 | use alloc::string::String; 8 | use core::str::FromStr; 9 | 10 | use base64ct::{Base64, Encoding}; 11 | use sentc_crypto_common::SymKeyId; 12 | use sentc_crypto_utils::error::SdkUtilError; 13 | use sentc_crypto_utils::{from_string_impl, to_string_impl}; 14 | use serde::{Deserialize, Serialize}; 15 | 16 | use crate::core::{HmacKey as CoreHmacKey, SortKeys as CoreSortableKey}; 17 | 18 | //__________________________________________________________________________________________________ 19 | //impl them here because they are only used when encryption is enabled 20 | 21 | pub struct HmacKey 22 | { 23 | pub key: CoreHmacKey, 24 | pub key_id: SymKeyId, 25 | } 26 | 27 | to_string_impl!(HmacKey, HmacFormatExport); 28 | from_string_impl!(HmacKey, HmacFormatExport); 29 | 30 | #[derive(Serialize, Deserialize)] 31 | pub enum HmacFormatExport 32 | { 33 | HmacSha256 34 | { 35 | key: String, key_id: SymKeyId 36 | }, 37 | } 38 | 39 | impl From for HmacFormatExport 40 | { 41 | fn from(value: HmacKey) -> Self 42 | { 43 | let key = Base64::encode_string(value.key.as_ref()); 44 | 45 | match value.key { 46 | CoreHmacKey::HmacSha256(_) => { 47 | Self::HmacSha256 { 48 | key, 49 | key_id: value.key_id, 50 | } 51 | }, 52 | } 53 | } 54 | } 55 | 56 | impl<'a> From<&'a HmacKey> for HmacFormatExport 57 | { 58 | fn from(value: &'a HmacKey) -> Self 59 | { 60 | let key = Base64::encode_string(value.key.as_ref()); 61 | 62 | match value.key { 63 | CoreHmacKey::HmacSha256(_) => { 64 | Self::HmacSha256 { 65 | key, 66 | key_id: value.key_id.clone(), 67 | } 68 | }, 69 | } 70 | } 71 | } 72 | 73 | impl TryInto for HmacFormatExport 74 | { 75 | type Error = SdkUtilError; 76 | 77 | fn try_into(self) -> Result 78 | { 79 | match self { 80 | HmacFormatExport::HmacSha256 { 81 | key, 82 | key_id, 83 | } => { 84 | let bytes = Base64::decode_vec(&key).map_err(|_| SdkUtilError::ImportSymmetricKeyFailed)?; 85 | 86 | Ok(HmacKey { 87 | key: CoreHmacKey::hmac_sha256_from_bytes_owned(bytes)?, 88 | key_id, 89 | }) 90 | }, 91 | } 92 | } 93 | } 94 | 95 | //__________________________________________________________________________________________________ 96 | 97 | pub struct SortableKey 98 | { 99 | pub key: CoreSortableKey, 100 | pub key_id: SymKeyId, 101 | } 102 | 103 | to_string_impl!(SortableKey, SortableFormatExport); 104 | from_string_impl!(SortableKey, SortableFormatExport); 105 | 106 | #[derive(Serialize, Deserialize)] 107 | pub enum SortableFormatExport 108 | { 109 | Ope16 110 | { 111 | key: String, key_id: SymKeyId 112 | }, 113 | } 114 | 115 | impl From for SortableFormatExport 116 | { 117 | fn from(value: SortableKey) -> Self 118 | { 119 | let key = Base64::encode_string(value.key.as_ref()); 120 | 121 | match value.key { 122 | CoreSortableKey::Ope(_) => { 123 | Self::Ope16 { 124 | key, 125 | key_id: value.key_id, 126 | } 127 | }, 128 | } 129 | } 130 | } 131 | 132 | impl<'a> From<&'a SortableKey> for SortableFormatExport 133 | { 134 | fn from(value: &'a SortableKey) -> Self 135 | { 136 | let key = Base64::encode_string(value.key.as_ref()); 137 | 138 | match value.key { 139 | CoreSortableKey::Ope(_) => { 140 | Self::Ope16 { 141 | key, 142 | key_id: value.key_id.clone(), 143 | } 144 | }, 145 | } 146 | } 147 | } 148 | 149 | impl TryInto for SortableFormatExport 150 | { 151 | type Error = SdkUtilError; 152 | 153 | fn try_into(self) -> Result 154 | { 155 | match self { 156 | SortableFormatExport::Ope16 { 157 | key, 158 | key_id, 159 | } => { 160 | let bytes = Base64::decode_vec(&key).map_err(|_| SdkUtilError::ImportSymmetricKeyFailed)?; 161 | 162 | Ok(SortableKey { 163 | key: CoreSortableKey::ope_key_from_bytes_owned(bytes)?, 164 | key_id, 165 | }) 166 | }, 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/util/crypto/searchable.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | 3 | use base64ct::{Base64UrlUnpadded, Encoding}; 4 | use sentc_crypto_core::cryptomat::SearchableKey; 5 | use sentc_crypto_utils::cryptomat::SearchableKeyWrapper; 6 | use sentc_crypto_utils::error::SdkUtilError; 7 | use sentc_crypto_utils::search_key_composer; 8 | 9 | use crate::core::HmacKey as CoreHmacKey; 10 | use crate::util::HmacKey; 11 | 12 | search_key_composer!(HmacKey, CoreHmacKey); 13 | 14 | impl SearchableKeyWrapper for HmacKey 15 | { 16 | type Inner = CoreHmacKey; 17 | 18 | fn get_id(&self) -> &str 19 | { 20 | &self.key_id 21 | } 22 | 23 | fn get_key(&self) -> &Self::Inner 24 | { 25 | &self.key 26 | } 27 | 28 | fn search_bytes(&self, data: &[u8]) -> Result 29 | { 30 | let hash = self.key.encrypt_searchable(data)?; 31 | 32 | Ok(Base64UrlUnpadded::encode_string(&hash)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/util/crypto/sign.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::ToString; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_common::crypto::SignHead; 5 | use sentc_crypto_common::user::UserVerifyKeyData; 6 | use sentc_crypto_core::cryptomat::{CryptoAlg, SignK}; 7 | use sentc_crypto_utils::cryptomat::{SignKCryptoWrapper, VerifyKFromUserKeyWrapper}; 8 | use sentc_crypto_utils::error::SdkUtilError; 9 | 10 | use crate::core::{Signature, VerifyKey as CoreVk}; 11 | use crate::util::{import_verify_key_from_pem_with_alg, SignKey, VerifyKey}; 12 | 13 | impl VerifyKFromUserKeyWrapper for VerifyKey 14 | { 15 | type CoreVk = CoreVk; 16 | 17 | fn split_sig_and_data<'a>(alg: &str, data_with_sign: &'a [u8]) -> Result<(&'a [u8], &'a [u8]), SdkUtilError> 18 | { 19 | Ok(Signature::split_sig_and_data(alg, data_with_sign)?) 20 | } 21 | 22 | fn from_user_key(verify_key: &UserVerifyKeyData) -> Result 23 | { 24 | import_verify_key_from_pem_with_alg(&verify_key.verify_key_pem, &verify_key.verify_key_alg) 25 | } 26 | } 27 | 28 | impl SignKCryptoWrapper for SignKey 29 | { 30 | fn sign_with_head(&self, data: &[u8]) -> Result<(SignHead, Vec), SdkUtilError> 31 | { 32 | let sig = self.key.sign(data)?; 33 | 34 | Ok(( 35 | SignHead { 36 | id: self.key_id.clone(), 37 | alg: self.key.get_alg_str().to_string(), 38 | }, 39 | sig, 40 | )) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/util/crypto/sortable.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::{String, ToString}; 2 | use core::cmp::Ordering; 3 | 4 | use sentc_crypto_common::content_sortable::SortableEncryptOutput; 5 | use sentc_crypto_core::cryptomat::{CryptoAlg, SortableKey as CoreSortableI}; 6 | use sentc_crypto_utils::cryptomat::SortableKeyWrapper; 7 | use sentc_crypto_utils::error::SdkUtilError; 8 | use sentc_crypto_utils::sortable_composer; 9 | 10 | use crate::core::SortKeys as CoreSortableKey; 11 | use crate::util::SortableKey; 12 | 13 | sortable_composer!(SortableKey, CoreSortableKey); 14 | 15 | impl SortableKeyWrapper for SortableKey 16 | { 17 | type Inner = CoreSortableKey; 18 | 19 | fn get_id(&self) -> &str 20 | { 21 | &self.key_id 22 | } 23 | 24 | fn get_key(&self) -> &Self::Inner 25 | { 26 | &self.key 27 | } 28 | 29 | fn encrypt_raw_string(&self, data: &str, max_len: Option) -> Result 30 | { 31 | let n = Self::prepare_string(data, max_len.unwrap_or(4)); 32 | 33 | Ok(self.key.encrypt_sortable(n)?) 34 | } 35 | 36 | fn encrypt_string(&self, data: &str, max_len: Option) -> Result 37 | { 38 | let number = self.encrypt_raw_string(data, max_len)?; 39 | 40 | Ok(SortableEncryptOutput { 41 | number, 42 | alg: self.key.get_alg_str().to_string(), 43 | key_id: self.key_id.clone(), 44 | }) 45 | } 46 | } 47 | 48 | impl SortableKey 49 | { 50 | fn transform_string_to_number(s: &str) -> u64 51 | { 52 | let mut number: u64 = 0; 53 | 54 | for c in s.chars() { 55 | let ascii_value = c as u64; 56 | number = number * 256 + ascii_value; 57 | } 58 | 59 | number / (u16::MAX as u64 - 1) 60 | } 61 | 62 | fn prepare_string(data: &str, max_len: usize) -> u64 63 | { 64 | match data.len().cmp(&max_len) { 65 | Ordering::Greater => Self::transform_string_to_number(&data[..max_len]), 66 | Ordering::Less => { 67 | //fill it with dummy chars to get the len 68 | let mut st = data.to_string(); 69 | 70 | for _i in data.len()..max_len { 71 | st += "*"; 72 | } 73 | 74 | Self::transform_string_to_number(&st) 75 | }, 76 | Ordering::Equal => Self::transform_string_to_number(data), 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/util/crypto/symmetric_key.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::{String, ToString}; 2 | use alloc::vec::Vec; 3 | 4 | use base64ct::{Base64, Encoding}; 5 | use sentc_crypto_common::crypto::EncryptedHead; 6 | use sentc_crypto_common::user::UserVerifyKeyData; 7 | use sentc_crypto_core::cryptomat::SymKey; 8 | use sentc_crypto_utils::cryptomat::{SignKWrapper, SymKeyCrypto}; 9 | use sentc_crypto_utils::error::SdkUtilError; 10 | 11 | use crate::util::{SymmetricKey, VerifyKey}; 12 | 13 | impl SymKeyCrypto for SymmetricKey 14 | { 15 | type VerifyKey = VerifyKey; 16 | 17 | fn encrypt_raw(&self, data: &[u8]) -> Result<(EncryptedHead, Vec), SdkUtilError> 18 | { 19 | let encrypted = self.key.encrypt(data)?; 20 | 21 | Ok(( 22 | EncryptedHead { 23 | id: self.key_id.to_string(), 24 | sign: None, 25 | }, 26 | encrypted, 27 | )) 28 | } 29 | 30 | fn encrypt_raw_with_sign(&self, data: &[u8], sign_key: &impl SignKWrapper) -> Result<(EncryptedHead, Vec), SdkUtilError> 31 | { 32 | let encrypted = self.key.encrypt(data)?; 33 | 34 | let (sign_head, data_with_sign) = sign_key.sign_with_head(&encrypted)?; 35 | 36 | Ok(( 37 | EncryptedHead { 38 | id: self.key_id.to_string(), 39 | sign: Some(sign_head), 40 | }, 41 | data_with_sign, 42 | )) 43 | } 44 | 45 | fn encrypt_raw_with_aad(&self, data: &[u8], aad: &[u8]) -> Result<(EncryptedHead, Vec), SdkUtilError> 46 | { 47 | let encrypted = self.key.encrypt_with_aad(data, aad)?; 48 | 49 | Ok(( 50 | EncryptedHead { 51 | id: self.key_id.to_string(), 52 | sign: None, 53 | }, 54 | encrypted, 55 | )) 56 | } 57 | 58 | fn encrypt_raw_with_aad_with_sign(&self, data: &[u8], aad: &[u8], sign_key: &impl SignKWrapper) 59 | -> Result<(EncryptedHead, Vec), SdkUtilError> 60 | { 61 | let encrypted = self.key.encrypt_with_aad(data, aad)?; 62 | 63 | let (sign_head, data_with_sign) = sign_key.sign_with_head(&encrypted)?; 64 | 65 | Ok(( 66 | EncryptedHead { 67 | id: self.key_id.to_string(), 68 | sign: Some(sign_head), 69 | }, 70 | data_with_sign, 71 | )) 72 | } 73 | 74 | fn decrypt_raw(&self, encrypted_data: &[u8], head: &EncryptedHead, verify_key: Option<&UserVerifyKeyData>) -> Result, SdkUtilError> 75 | { 76 | let data_to_decrypt = Self::prepare_decrypt(encrypted_data, head, verify_key)?; 77 | 78 | Ok(self.key.decrypt(data_to_decrypt)?) 79 | } 80 | 81 | fn decrypt_raw_with_aad( 82 | &self, 83 | encrypted_data: &[u8], 84 | aad: &[u8], 85 | head: &EncryptedHead, 86 | verify_key: Option<&UserVerifyKeyData>, 87 | ) -> Result, SdkUtilError> 88 | { 89 | let data_to_decrypt = Self::prepare_decrypt(encrypted_data, head, verify_key)?; 90 | 91 | Ok(self.key.decrypt_with_aad(data_to_decrypt, aad)?) 92 | } 93 | 94 | fn encrypt_string(&self, data: &str) -> Result 95 | { 96 | let encrypted = self.encrypt(data.as_bytes())?; 97 | 98 | Ok(Base64::encode_string(&encrypted)) 99 | } 100 | 101 | fn encrypt_string_with_sign(&self, data: &str, sign_key: &impl SignKWrapper) -> Result 102 | { 103 | let encrypted = self.encrypt_with_sign(data.as_bytes(), sign_key)?; 104 | 105 | Ok(Base64::encode_string(&encrypted)) 106 | } 107 | 108 | fn encrypt_string_with_aad(&self, data: &str, aad: &str) -> Result 109 | { 110 | let encrypted = self.encrypt_with_aad(data.as_bytes(), aad.as_bytes())?; 111 | 112 | Ok(Base64::encode_string(&encrypted)) 113 | } 114 | 115 | fn encrypt_string_with_aad_with_sign(&self, data: &str, aad: &str, sign_key: &impl SignKWrapper) -> Result 116 | { 117 | let encrypted = self.encrypt_with_aad_with_sign(data.as_bytes(), aad.as_bytes(), sign_key)?; 118 | 119 | Ok(Base64::encode_string(&encrypted)) 120 | } 121 | 122 | fn decrypt_string(&self, encrypted_data_with_head: &str, verify_key: Option<&UserVerifyKeyData>) -> Result 123 | { 124 | let encrypted = Base64::decode_vec(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 125 | 126 | let decrypted = self.decrypt(&encrypted, verify_key)?; 127 | 128 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 129 | } 130 | 131 | fn decrypt_string_with_aad( 132 | &self, 133 | encrypted_data_with_head: &str, 134 | aad: &str, 135 | verify_key: Option<&UserVerifyKeyData>, 136 | ) -> Result 137 | { 138 | let encrypted = Base64::decode_vec(encrypted_data_with_head).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed)?; 139 | 140 | let decrypted = self.decrypt_with_aad(&encrypted, aad.as_bytes(), verify_key)?; 141 | 142 | String::from_utf8(decrypted).map_err(|_| SdkUtilError::DecodeEncryptedDataFailed) 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /crypto_keys/crypto_std_keys/src/util/export.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | 3 | use base64ct::{Base64, Encoding}; 4 | use sentc_crypto_utils::error::SdkUtilError; 5 | use sentc_crypto_utils::{export_key_to_pem, import_key_from_pem}; 6 | 7 | use crate::core::{ 8 | PublicKey, 9 | Signature, 10 | VerifyKey, 11 | DILITHIUM_OUTPUT, 12 | ECIES_KYBER_HYBRID_OUTPUT, 13 | ECIES_OUTPUT, 14 | ED25519_DILITHIUM_HYBRID_OUTPUT, 15 | ED25519_OUTPUT, 16 | KYBER_OUTPUT, 17 | }; 18 | use crate::util::HybridPublicKeyExportFormat; 19 | 20 | pub fn import_public_key_from_pem_with_alg(public_key: &str, alg: &str) -> Result 21 | { 22 | match alg { 23 | ECIES_OUTPUT => { 24 | let bytes = import_key_from_pem(public_key)?; 25 | Ok(PublicKey::ecies_from_bytes_owned(bytes)?) 26 | }, 27 | KYBER_OUTPUT => { 28 | let bytes = import_key_from_pem(public_key)?; 29 | Ok(PublicKey::kyber_from_bytes_owned(bytes)?) 30 | }, 31 | ECIES_KYBER_HYBRID_OUTPUT => { 32 | let key: HybridPublicKeyExportFormat = serde_json::from_str(public_key).map_err(SdkUtilError::JsonParseFailed)?; 33 | 34 | let bytes_x = import_key_from_pem(&key.x)?; 35 | let bytes_k = import_key_from_pem(&key.k)?; 36 | 37 | Ok(PublicKey::ecies_kyber_hybrid_from_bytes_owned(bytes_x, bytes_k)?) 38 | }, 39 | _ => Err(SdkUtilError::AlgNotFound), 40 | } 41 | } 42 | 43 | pub fn import_verify_key_from_pem_with_alg(verify_key: &str, alg: &str) -> Result 44 | { 45 | match alg { 46 | ED25519_OUTPUT => { 47 | let bytes = import_key_from_pem(verify_key)?; 48 | Ok(VerifyKey::ed25519_from_bytes_owned(bytes)?) 49 | }, 50 | DILITHIUM_OUTPUT => { 51 | let bytes = import_key_from_pem(verify_key)?; 52 | Ok(VerifyKey::dilithium_from_bytes_owned(bytes)?) 53 | }, 54 | ED25519_DILITHIUM_HYBRID_OUTPUT => { 55 | let key: HybridPublicKeyExportFormat = serde_json::from_str(verify_key).map_err(SdkUtilError::JsonParseFailed)?; 56 | 57 | let bytes_x = import_key_from_pem(&key.x)?; 58 | let bytes_k = import_key_from_pem(&key.k)?; 59 | 60 | Ok(VerifyKey::ed25519_dilithium_hybrid_from_bytes_owned( 61 | bytes_x, bytes_k, 62 | )?) 63 | }, 64 | _ => Err(SdkUtilError::AlgNotFound), 65 | } 66 | } 67 | 68 | pub fn import_sig_from_string(sig: &str, alg: &str) -> Result 69 | { 70 | match alg { 71 | ED25519_OUTPUT => { 72 | let bytes = Base64::decode_vec(sig).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 73 | Ok(Signature::ed25519_from_bytes_owned(bytes)?) 74 | }, 75 | DILITHIUM_OUTPUT => { 76 | let bytes = Base64::decode_vec(sig).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 77 | Ok(Signature::dilithium_from_bytes_owned(bytes)?) 78 | }, 79 | ED25519_DILITHIUM_HYBRID_OUTPUT => { 80 | let key: HybridPublicKeyExportFormat = serde_json::from_str(sig).map_err(SdkUtilError::JsonParseFailed)?; 81 | 82 | let x = Base64::decode_vec(&key.x).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 83 | let k = Base64::decode_vec(&key.k).map_err(|_| SdkUtilError::DecodePublicKeyFailed)?; 84 | 85 | Ok(Signature::ed25519_dilithium_hybrid_from_bytes_owned(x, k)?) 86 | }, 87 | _ => Err(SdkUtilError::AlgNotFound), 88 | } 89 | } 90 | 91 | pub fn sig_to_string(sig: &Signature) -> String 92 | { 93 | match sig { 94 | Signature::Ed25519(s) => Base64::encode_string(s.as_ref()), 95 | Signature::Dilithium(s) => Base64::encode_string(s.as_ref()), 96 | Signature::Ed25519DilithiumHybrid(s) => { 97 | let (x, k) = s.get_raw_keys(); 98 | 99 | let x = Base64::encode_string(x); 100 | let k = Base64::encode_string(k); 101 | 102 | serde_json::to_string(&HybridPublicKeyExportFormat { 103 | x, 104 | k, 105 | }) 106 | .unwrap() 107 | }, 108 | } 109 | } 110 | 111 | pub fn export_raw_public_key_to_pem(key: &PublicKey) -> Result 112 | { 113 | match key { 114 | //match against the public key variants 115 | PublicKey::Ecies(k) => export_key_to_pem(k.as_ref()), 116 | PublicKey::Kyber(k) => export_key_to_pem(k.as_ref()), 117 | PublicKey::EciesKyberHybrid(key) => { 118 | let (x, k) = key.get_raw_keys(); 119 | 120 | let x = export_key_to_pem(x)?; 121 | let k = export_key_to_pem(k)?; 122 | 123 | serde_json::to_string(&HybridPublicKeyExportFormat { 124 | x, 125 | k, 126 | }) 127 | .map_err(|_| SdkUtilError::JsonToStringFailed) 128 | }, 129 | } 130 | } 131 | 132 | pub fn export_raw_verify_key_to_pem(key: &VerifyKey) -> Result 133 | { 134 | match key { 135 | VerifyKey::Ed25519(k) => export_key_to_pem(k.as_ref()), 136 | VerifyKey::Dilithium(k) => export_key_to_pem(k.as_ref()), 137 | VerifyKey::Ed25519DilithiumHybrid(key) => { 138 | let (x, k) = key.get_raw_keys(); 139 | 140 | let x = export_key_to_pem(x)?; 141 | let k = export_key_to_pem(k)?; 142 | 143 | serde_json::to_string(&HybridPublicKeyExportFormat { 144 | x, 145 | k, 146 | }) 147 | .map_err(|_| SdkUtilError::JsonToStringFailed) 148 | }, 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /crypto_light/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc-crypto-light" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | homepage.workspace = true 7 | authors.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | 11 | description = "The main implementation of the sentc light sdk." 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | include = [ 16 | "Cargo.toml", 17 | "../LICENSE", 18 | "src/**/*", 19 | ] 20 | 21 | [dependencies] 22 | sentc-crypto-common = { workspace = true } 23 | sentc-crypto-core = { workspace = true } 24 | sentc-crypto-utils = { workspace = true } 25 | sentc-crypto-std-keys = { workspace = true, features = ["wrapper"] } 26 | 27 | # json handling 28 | serde_json.workspace = true 29 | serde.workspace = true 30 | 31 | # key and data export 32 | base64ct.workspace = true 33 | 34 | [features] 35 | export = [] 36 | 37 | server_test = [] 38 | 39 | full_rustls = ["sentc-crypto-utils/crypto_full", "sentc-crypto-utils/rustls"] 40 | full_wasm = ["sentc-crypto-utils/crypto_full", "sentc-crypto-utils/wasm"] -------------------------------------------------------------------------------- /crypto_light/src/error.rs: -------------------------------------------------------------------------------- 1 | use alloc::format; 2 | use alloc::string::String; 3 | 4 | use sentc_crypto_core::Error; 5 | use sentc_crypto_utils::error::{out_error, SdkUtilError}; 6 | 7 | #[derive(Debug)] 8 | pub enum SdkLightError 9 | { 10 | Util(SdkUtilError), 11 | JsonToStringFailed, 12 | JsonParseFailed(serde_json::Error), 13 | KeyDecryptFailed, 14 | GroupPermission, 15 | GroupRank, 16 | } 17 | 18 | /** 19 | To convert the core error to sdk error 20 | */ 21 | impl From for SdkLightError 22 | { 23 | fn from(e: Error) -> Self 24 | { 25 | SdkLightError::Util(SdkUtilError::Base(e)) 26 | } 27 | } 28 | 29 | impl From for SdkLightError 30 | { 31 | fn from(value: SdkUtilError) -> Self 32 | { 33 | Self::Util(value) 34 | } 35 | } 36 | 37 | impl From for String 38 | { 39 | fn from(e: SdkLightError) -> Self 40 | { 41 | err_to_msg(e) 42 | } 43 | } 44 | 45 | impl From for SdkLightError 46 | { 47 | fn from(value: serde_json::Error) -> Self 48 | { 49 | Self::JsonParseFailed(value) 50 | } 51 | } 52 | 53 | pub fn err_to_msg(error: SdkLightError) -> String 54 | { 55 | match error { 56 | SdkLightError::Util(e) => sentc_crypto_utils::error::err_to_msg(e), 57 | SdkLightError::JsonToStringFailed => out_error("client_100", "Cannot create a string from this object"), 58 | SdkLightError::JsonParseFailed(err) => { 59 | format!("{{\"status\": {}, \"error_message\": \"{}\"}}", "client_101", err) 60 | }, 61 | SdkLightError::KeyDecryptFailed => out_error("client_21", "Can't decrypt a key. Maybe the format is wrong"), 62 | 63 | //group error 64 | SdkLightError::GroupRank => { 65 | out_error( 66 | "client_200", 67 | "No valid group rank. Please choose between 1 (highest) and 4 (lowest)", 68 | ) 69 | }, 70 | SdkLightError::GroupPermission => out_error("client_201", "No permission to fulfill this action"), 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /crypto_light/src/group.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::{String, ToString}; 2 | 3 | use sentc_crypto_common::group::{GroupChangeRankServerInput, GroupLightServerData}; 4 | use sentc_crypto_utils::group::GroupOutDataLight; 5 | use sentc_crypto_utils::handle_server_response; 6 | 7 | use crate::error::SdkLightError; 8 | 9 | #[cfg(feature = "export")] 10 | pub fn get_group_light_data(server_output: &str) -> Result 11 | { 12 | let out = get_group_light_data_internally(server_output)?; 13 | 14 | Ok(out.into()) 15 | } 16 | 17 | #[cfg(not(feature = "export"))] 18 | pub fn get_group_light_data(server_output: &str) -> Result 19 | { 20 | get_group_light_data_internally(server_output) 21 | } 22 | 23 | fn get_group_light_data_internally(server_output: &str) -> Result 24 | { 25 | let server_output: GroupLightServerData = handle_server_response(server_output)?; 26 | 27 | let (access_by_group_as_member, access_by_parent_group) = sentc_crypto_utils::group::get_access_by(server_output.access_by); 28 | 29 | Ok(GroupOutDataLight { 30 | group_id: server_output.group_id, 31 | parent_group_id: server_output.parent_group_id, 32 | rank: server_output.rank, 33 | created_time: server_output.created_time, 34 | joined_time: server_output.joined_time, 35 | is_connected_group: server_output.is_connected_group, 36 | access_by_group_as_member, 37 | access_by_parent_group, 38 | }) 39 | } 40 | 41 | //__________________________________________________________________________________________________ 42 | 43 | #[cfg(feature = "export")] 44 | pub fn prepare_change_rank(user_id: &str, new_rank: i32, admin_rank: i32) -> Result 45 | { 46 | Ok(prepare_change_rank_internally(user_id, new_rank, admin_rank)?) 47 | } 48 | 49 | #[cfg(not(feature = "export"))] 50 | pub fn prepare_change_rank(user_id: &str, new_rank: i32, admin_rank: i32) -> Result 51 | { 52 | prepare_change_rank_internally(user_id, new_rank, admin_rank) 53 | } 54 | 55 | fn prepare_change_rank_internally(user_id: &str, new_rank: i32, admin_rank: i32) -> Result 56 | { 57 | #[allow(clippy::manual_range_contains)] 58 | if new_rank < 1 || new_rank > 4 { 59 | return Err(SdkLightError::GroupRank); 60 | } 61 | 62 | if admin_rank > 1 { 63 | return Err(SdkLightError::GroupPermission); 64 | } 65 | 66 | GroupChangeRankServerInput { 67 | changed_user_id: user_id.to_string(), 68 | new_rank, 69 | } 70 | .to_string() 71 | .map_err(|_| SdkLightError::JsonToStringFailed) 72 | } 73 | -------------------------------------------------------------------------------- /crypto_light/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | extern crate alloc; 4 | 5 | pub mod error; 6 | pub mod group; 7 | pub mod user; 8 | #[cfg(any(feature = "full_rustls", feature = "full_wasm"))] 9 | pub mod util_req_full; 10 | 11 | use alloc::string::String; 12 | 13 | #[cfg(feature = "server_test")] 14 | pub use sentc_crypto_common as sdk_common; 15 | use sentc_crypto_common::{DeviceId, UserId}; 16 | use sentc_crypto_utils::cryptomat::KeyToString; 17 | use serde::{Deserialize, Serialize}; 18 | pub use {sentc_crypto_core as sdk_core, sentc_crypto_utils as sdk_utils, sentc_crypto_std_keys as sdk_keys}; 19 | 20 | use crate::error::SdkLightError; 21 | 22 | pub type StdDeviceKeyDataInt = sentc_crypto_utils::user::DeviceKeyDataInt< 23 | sentc_crypto_std_keys::util::SecretKey, 24 | sentc_crypto_std_keys::util::PublicKey, 25 | sentc_crypto_std_keys::util::SignKey, 26 | sentc_crypto_std_keys::util::VerifyKey, 27 | >; 28 | pub type StdUserPreVerifyLogin = sentc_crypto_utils::user::UserPreVerifyLogin< 29 | sentc_crypto_std_keys::util::SecretKey, 30 | sentc_crypto_std_keys::util::PublicKey, 31 | sentc_crypto_std_keys::util::SignKey, 32 | sentc_crypto_std_keys::util::VerifyKey, 33 | >; 34 | 35 | pub struct UserDataInt 36 | { 37 | pub jwt: String, 38 | pub refresh_token: String, 39 | pub user_id: UserId, 40 | pub device_id: DeviceId, 41 | 42 | pub device_keys: StdDeviceKeyDataInt, 43 | } 44 | 45 | #[derive(Serialize, Deserialize)] 46 | pub struct UserDataExport 47 | { 48 | pub device_keys: DeviceKeyDataExport, 49 | pub jwt: String, 50 | pub refresh_token: String, 51 | pub user_id: UserId, 52 | pub device_id: DeviceId, 53 | } 54 | 55 | impl TryFrom for UserDataExport 56 | { 57 | type Error = SdkLightError; 58 | 59 | fn try_from(value: UserDataInt) -> Result 60 | { 61 | Ok(Self { 62 | device_keys: value.device_keys.try_into()?, 63 | jwt: value.jwt, 64 | refresh_token: value.refresh_token, 65 | user_id: value.user_id, 66 | device_id: value.device_id, 67 | }) 68 | } 69 | } 70 | 71 | #[derive(Serialize, Deserialize)] 72 | pub struct DeviceKeyDataExport 73 | { 74 | pub private_key: String, //Base64 exported keys 75 | pub public_key: String, 76 | pub sign_key: String, 77 | pub verify_key: String, 78 | pub exported_public_key: String, 79 | pub exported_verify_key: String, 80 | } 81 | 82 | impl TryFrom for DeviceKeyDataExport 83 | { 84 | type Error = SdkLightError; 85 | 86 | fn try_from(value: StdDeviceKeyDataInt) -> Result 87 | { 88 | Ok(Self { 89 | private_key: value.private_key.to_string()?, 90 | public_key: value.public_key.to_string()?, 91 | sign_key: value.sign_key.to_string()?, 92 | verify_key: value.verify_key.to_string()?, 93 | exported_public_key: value 94 | .exported_public_key 95 | .to_string() 96 | .map_err(|_e| SdkLightError::JsonToStringFailed)?, 97 | exported_verify_key: value 98 | .exported_verify_key 99 | .to_string() 100 | .map_err(|_e| SdkLightError::JsonToStringFailed)?, 101 | }) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /crypto_light/src/util_req_full/group/non_rust.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_common::group::{GroupChildrenList, GroupInviteReqList, GroupJoinReqList, GroupUserListItem, ListGroups}; 5 | use sentc_crypto_utils::group::GroupOutDataLightExport; 6 | 7 | pub type Res = Result; 8 | pub type VoidRes = Result<(), String>; 9 | pub type DataRes = Result; 10 | pub type MemberRes = Result, String>; 11 | pub type UserUpdateCheckRes = Result; 12 | pub type InviteListRes = Result, String>; 13 | pub type JoinReqListRes = Result, String>; 14 | pub type GroupListRes = Result, String>; 15 | pub type ChildrenRes = Result, String>; 16 | -------------------------------------------------------------------------------- /crypto_light/src/util_req_full/group/rust.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_common::group::{GroupChildrenList, GroupInviteReqList, GroupJoinReqList, GroupUserListItem, ListGroups}; 5 | use sentc_crypto_utils::group::GroupOutDataLight; 6 | 7 | use crate::error::SdkLightError; 8 | 9 | pub type Res = Result; 10 | pub type VoidRes = Result<(), SdkLightError>; 11 | pub type DataRes = Result; 12 | pub type MemberRes = Result, SdkLightError>; 13 | pub type UserUpdateCheckRes = Result; 14 | pub type InviteListRes = Result, SdkLightError>; 15 | pub type JoinReqListRes = Result, SdkLightError>; 16 | pub type GroupListRes = Result, SdkLightError>; 17 | pub type ChildrenRes = Result, SdkLightError>; 18 | -------------------------------------------------------------------------------- /crypto_light/src/util_req_full/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod group; 2 | pub mod user; 3 | 4 | use sentc_crypto_common::user::Claims; 5 | 6 | #[cfg(not(feature = "export"))] 7 | pub(crate) type JwtRes = Result; 8 | 9 | #[cfg(feature = "export")] 10 | pub(crate) type JwtRes = Result; 11 | 12 | #[allow(clippy::needless_question_mark)] 13 | pub fn decode_jwt(token: &str) -> JwtRes 14 | { 15 | Ok(sentc_crypto_utils::jwt::decode_jwt(token)?) 16 | } 17 | -------------------------------------------------------------------------------- /crypto_light/src/util_req_full/user/non_rust.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_common::user::{OtpRecoveryKeysOutput, OtpRegister, UserDeviceList, UserInitServerOutput}; 5 | 6 | use crate::UserDataExport; 7 | 8 | pub struct PrepareLoginOtpOutput 9 | { 10 | pub master_key: String, 11 | pub auth_key: String, 12 | } 13 | 14 | #[allow(clippy::large_enum_variant)] 15 | pub enum PreLoginOut 16 | { 17 | Direct(UserDataExport), 18 | Otp(PrepareLoginOtpOutput), 19 | } 20 | 21 | pub type Res = Result; 22 | pub type VoidRes = Result<(), String>; 23 | pub type BoolRes = Result; 24 | pub type PreLoginRes = Result; 25 | pub type LoginRes = Result; 26 | pub type InitRes = Result; 27 | pub type DeviceListRes = Result, String>; 28 | 29 | pub type RegisterRawOtpRes = Result; 30 | pub type RegisterOtpRes = Result<(String, Vec), String>; 31 | pub type OtpRecoveryKeyRes = Result; 32 | -------------------------------------------------------------------------------- /crypto_light/src/util_req_full/user/rust.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use alloc::vec::Vec; 3 | 4 | use sentc_crypto_common::user::{OtpRecoveryKeysOutput, OtpRegister, UserDeviceList, UserInitServerOutput}; 5 | 6 | use crate::error::SdkLightError; 7 | use crate::UserDataInt; 8 | 9 | pub struct PrepareLoginOtpOutput 10 | { 11 | pub master_key: sentc_crypto_std_keys::core::DeriveMasterKeyForAuth, 12 | pub auth_key: String, 13 | } 14 | 15 | #[allow(clippy::large_enum_variant)] 16 | pub enum PreLoginOut 17 | { 18 | Direct(UserDataInt), 19 | Otp(PrepareLoginOtpOutput), 20 | } 21 | 22 | pub type Res = Result; 23 | pub type VoidRes = Result<(), SdkLightError>; 24 | pub type BoolRes = Result; 25 | pub type PreLoginRes = Result; 26 | pub type LoginRes = Result; 27 | pub type InitRes = Result; 28 | pub type DeviceListRes = Result, SdkLightError>; 29 | 30 | pub type RegisterRawOtpRes = Result; 31 | pub type RegisterOtpRes = Result<(String, Vec), SdkLightError>; 32 | pub type OtpRecoveryKeyRes = Result; 33 | -------------------------------------------------------------------------------- /crypto_utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc-crypto-utils" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | homepage.workspace = true 7 | authors.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | 14 | description = "Common types and functions for sentc sdk and sdk light" 15 | 16 | include = [ 17 | "Cargo.toml", 18 | "../LICENSE", 19 | "src/**/*", 20 | ] 21 | 22 | [dependencies] 23 | sentc-crypto-common = { workspace = true } 24 | 25 | sentc-crypto-core = { workspace = true } 26 | 27 | # json handling 28 | serde_json.workspace = true 29 | serde.workspace = true 30 | 31 | # key and data export 32 | base64ct.workspace = true 33 | pem-rfc7468 = { version = "0.3.1", features = ["alloc"] } 34 | 35 | #_______________________________________________________________________________________________________________________ 36 | # req handling 37 | reqwest = { version = "0.11.27", optional = true, default-features = false } 38 | 39 | wasm-bindgen = { version = "0.2.74", optional = true } 40 | 41 | wasm-bindgen-futures = { version = "0.4.31", optional = true } 42 | 43 | web-sys = { version = "0.3.4", optional = true, features = ['Headers', 'Request', 'RequestInit', 'RequestMode', 'Response', 'Window'] } 44 | 45 | js-sys = { version = "0.3.58", optional = true } 46 | 47 | 48 | [features] 49 | # req handling 50 | rustls = ["reqwest/rustls-tls"] 51 | wasm = ["wasm-bindgen", "wasm-bindgen-futures", "web-sys", "js-sys"] 52 | 53 | crypto_full = [] 54 | encryption = [] -------------------------------------------------------------------------------- /crypto_utils/src/full/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod user; 2 | -------------------------------------------------------------------------------- /crypto_utils/src/group.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | 3 | use sentc_crypto_common::group::GroupUserAccessBy; 4 | use sentc_crypto_common::GroupId; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | pub fn get_access_by(access_by: GroupUserAccessBy) -> (Option, Option) 8 | { 9 | match access_by { 10 | GroupUserAccessBy::User => (None, None), 11 | GroupUserAccessBy::Parent(id) => (None, Some(id)), 12 | GroupUserAccessBy::GroupAsUser(id) => (Some(id), None), 13 | GroupUserAccessBy::GroupAsUserAsParent { 14 | parent, 15 | group_as_user, 16 | } => (Some(group_as_user), Some(parent)), 17 | } 18 | } 19 | 20 | pub struct GroupOutDataLight 21 | { 22 | pub group_id: GroupId, 23 | pub parent_group_id: Option, 24 | pub rank: i32, 25 | pub created_time: u128, 26 | pub joined_time: u128, 27 | pub access_by_group_as_member: Option, 28 | pub access_by_parent_group: Option, 29 | pub is_connected_group: bool, 30 | } 31 | 32 | //__________________________________________________________________________________________________ 33 | 34 | #[derive(Serialize, Deserialize)] 35 | pub struct GroupOutDataLightExport 36 | { 37 | pub group_id: String, 38 | pub parent_group_id: Option, 39 | pub rank: i32, 40 | pub created_time: u128, 41 | pub joined_time: u128, 42 | pub access_by_group_as_member: Option, 43 | pub access_by_parent_group: Option, 44 | pub is_connected_group: bool, 45 | } 46 | 47 | impl From for GroupOutDataLightExport 48 | { 49 | fn from(value: GroupOutDataLight) -> Self 50 | { 51 | Self { 52 | group_id: value.group_id, 53 | parent_group_id: value.parent_group_id, 54 | rank: value.rank, 55 | created_time: value.created_time, 56 | joined_time: value.joined_time, 57 | access_by_group_as_member: value.access_by_group_as_member, 58 | access_by_parent_group: value.access_by_parent_group, 59 | is_connected_group: value.is_connected_group, 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /crypto_utils/src/http/http_reqwest.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::{String, ToString}; 2 | use alloc::vec::Vec; 3 | 4 | use reqwest::header::AUTHORIZATION; 5 | use reqwest::Response; 6 | use sentc_crypto_common::server_default::ServerSuccessOutput; 7 | 8 | use crate::error::SdkUtilError; 9 | use crate::handle_server_response; 10 | use crate::http::{auth_header, HttpMethod}; 11 | 12 | pub async fn make_req( 13 | method: HttpMethod, 14 | url: &str, 15 | auth_token: &str, 16 | body: Option, 17 | jwt: Option<&str>, 18 | group_as_member: Option<&str>, 19 | ) -> Result 20 | { 21 | let res = make_req_raw(method, url, auth_token, body, jwt, group_as_member).await?; 22 | 23 | res.text().await.map_err(|_e| SdkUtilError::ResponseErrText) 24 | } 25 | 26 | pub async fn make_req_buffer( 27 | method: HttpMethod, 28 | url: &str, 29 | auth_token: &str, 30 | body: Option, 31 | jwt: Option<&str>, 32 | group_as_member: Option<&str>, 33 | ) -> Result, SdkUtilError> 34 | { 35 | let res = make_req_raw(method, url, auth_token, body, jwt, group_as_member).await?; 36 | 37 | if res.status().as_u16() >= 400 { 38 | let text = res 39 | .text() 40 | .await 41 | .map_err(|_e| SdkUtilError::ResponseErrText)?; 42 | handle_server_response::(text.as_str())?; 43 | return Ok(Vec::new()); 44 | } 45 | 46 | let buffer = res 47 | .bytes() 48 | .await 49 | .map_err(|_e| SdkUtilError::ResponseErrBytes)? 50 | .to_vec(); 51 | 52 | Ok(buffer) 53 | } 54 | 55 | pub async fn make_req_buffer_body( 56 | method: HttpMethod, 57 | url: &str, 58 | auth_token: &str, 59 | body: Vec, 60 | jwt: Option<&str>, 61 | group_as_member: Option<&str>, 62 | ) -> Result 63 | { 64 | let client = reqwest::Client::new(); 65 | 66 | let builder = match method { 67 | HttpMethod::GET => client.get(url), 68 | HttpMethod::POST => client.post(url), 69 | HttpMethod::PUT => client.put(url), 70 | HttpMethod::PATCH => client.patch(url), 71 | HttpMethod::DELETE => client.delete(url), 72 | }; 73 | 74 | let builder = builder.header("x-sentc-app-token", auth_token); 75 | 76 | let builder = match jwt { 77 | Some(j) => builder.header(AUTHORIZATION, auth_header(j)), 78 | None => builder, 79 | }; 80 | 81 | let builder = match group_as_member { 82 | Some(id) => builder.header("x-sentc-group-access-id", id), 83 | None => builder, 84 | }; 85 | 86 | let builder = builder.body(body); 87 | 88 | let res = builder 89 | .send() 90 | .await 91 | .map_err(|e| SdkUtilError::RequestErr(e.to_string()))?; 92 | 93 | res.text().await.map_err(|_e| SdkUtilError::ResponseErrText) 94 | } 95 | 96 | async fn make_req_raw( 97 | method: HttpMethod, 98 | url: &str, 99 | auth_token: &str, 100 | body: Option, 101 | jwt: Option<&str>, 102 | group_as_member: Option<&str>, 103 | ) -> Result 104 | { 105 | let client = reqwest::Client::new(); 106 | 107 | let builder = match method { 108 | HttpMethod::GET => client.get(url), 109 | HttpMethod::POST => client.post(url), 110 | HttpMethod::PUT => client.put(url), 111 | HttpMethod::PATCH => client.patch(url), 112 | HttpMethod::DELETE => client.delete(url), 113 | }; 114 | 115 | let builder = builder.header("x-sentc-app-token", auth_token); 116 | 117 | let builder = match jwt { 118 | Some(j) => builder.header(AUTHORIZATION, auth_header(j)), 119 | None => builder, 120 | }; 121 | 122 | let builder = match group_as_member { 123 | Some(id) => builder.header("x-sentc-group-access-id", id), 124 | None => builder, 125 | }; 126 | 127 | let builder = match body { 128 | None => builder, 129 | Some(b) => builder.body(b), 130 | }; 131 | 132 | let res = builder 133 | .send() 134 | .await 135 | .map_err(|e| SdkUtilError::RequestErr(e.to_string()))?; 136 | 137 | Ok(res) 138 | } 139 | -------------------------------------------------------------------------------- /crypto_utils/src/http/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rustls")] 2 | mod http_reqwest; 3 | #[cfg(feature = "wasm")] 4 | mod http_wasm; 5 | 6 | use alloc::string::{String, ToString}; 7 | use core::future::Future; 8 | 9 | #[cfg(feature = "rustls")] 10 | pub use http_reqwest::{make_req, make_req_buffer, make_req_buffer_body}; 11 | #[cfg(all(feature = "wasm", not(feature = "rustls")))] 12 | pub use http_wasm::{make_req, make_req_buffer, make_req_buffer_body}; 13 | 14 | use crate::error::SdkUtilError; 15 | 16 | pub fn auth_header(jwt: &str) -> String 17 | { 18 | "Bearer ".to_string() + jwt 19 | } 20 | 21 | pub enum HttpMethod 22 | { 23 | GET, 24 | POST, 25 | PUT, 26 | PATCH, 27 | DELETE, 28 | } 29 | 30 | pub fn non_auth_req<'a>( 31 | method: HttpMethod, 32 | url: &'a str, 33 | auth_token: &'a str, 34 | body: Option, 35 | ) -> impl Future> + 'a 36 | { 37 | make_req(method, url, auth_token, body, None, None) 38 | } 39 | 40 | pub fn auth_req<'a>( 41 | method: HttpMethod, 42 | url: &'a str, 43 | auth_token: &'a str, 44 | body: Option, 45 | jwt: &'a str, 46 | ) -> impl Future> + 'a 47 | { 48 | make_req(method, url, auth_token, body, Some(jwt), None) 49 | } 50 | 51 | pub fn normal_req<'a>( 52 | method: HttpMethod, 53 | url: &'a str, 54 | auth_token: &'a str, 55 | body: Option, 56 | jwt: Option<&'a str>, 57 | ) -> impl Future> + 'a 58 | { 59 | make_req(method, url, auth_token, body, jwt, None) 60 | } 61 | -------------------------------------------------------------------------------- /crypto_utils/src/jwt.rs: -------------------------------------------------------------------------------- 1 | use base64ct::Encoding; 2 | pub use sentc_crypto_common::user::Claims; 3 | 4 | use crate::error::SdkUtilError; 5 | 6 | //from the jsonwebtoken crate 7 | macro_rules! expect_two { 8 | ($iter:expr) => {{ 9 | let mut i = $iter; 10 | match (i.next(), i.next(), i.next()) { 11 | (Some(first), Some(second), None) => (first, second), 12 | _ => return Err(SdkUtilError::InvalidJwt), 13 | } 14 | }}; 15 | } 16 | 17 | pub fn decode_jwt(token: &str) -> Result 18 | { 19 | let (_, message) = expect_two!(token.rsplitn(2, '.')); 20 | let (claims, _header) = expect_two!(message.rsplitn(2, '.')); 21 | 22 | let decoded = base64ct::Base64UrlUnpadded::decode_vec(claims).map_err(|_e| SdkUtilError::InvalidJwtFormat)?; 23 | 24 | let claims: Claims = serde_json::from_slice(&decoded).map_err(|_e| SdkUtilError::InvalidJwtFormat)?; 25 | 26 | Ok(claims) 27 | } 28 | -------------------------------------------------------------------------------- /crypto_utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![allow(clippy::type_complexity)] 3 | 4 | extern crate alloc; 5 | 6 | use alloc::string::String; 7 | use alloc::vec::Vec; 8 | 9 | use base64ct::{Base64, Encoding}; 10 | use pem_rfc7468::LineEnding; 11 | use sentc_crypto_common::server_default::ServerSuccessOutput; 12 | use sentc_crypto_common::ServerOutput; 13 | use sentc_crypto_core::cryptomat::{ClientRandomValue, ClientRandomValueComposer, DeriveAuthKeyForAuth, HashedAuthenticationKey}; 14 | use serde::Deserialize; 15 | 16 | use crate::error::SdkUtilError; 17 | 18 | pub mod cryptomat; 19 | pub mod error; 20 | #[cfg(all(feature = "crypto_full", any(feature = "rustls", feature = "wasm")))] 21 | pub mod full; 22 | pub mod group; 23 | #[cfg(any(feature = "rustls", feature = "wasm"))] 24 | pub mod http; 25 | pub mod jwt; 26 | pub mod user; 27 | 28 | pub fn handle_server_response<'de, T: Deserialize<'de>>(res: &'de str) -> Result 29 | { 30 | let server_output = ServerOutput::::from_string(res)?; 31 | 32 | if !server_output.status { 33 | let err_code = match server_output.err_code { 34 | Some(c) => c, 35 | None => return Err(SdkUtilError::JsonParse), 36 | }; 37 | 38 | let err_msg = match server_output.err_msg { 39 | Some(m) => m, 40 | None => return Err(SdkUtilError::JsonParse), 41 | }; 42 | 43 | return Err(SdkUtilError::ServerErr(err_code, err_msg)); 44 | } 45 | 46 | match server_output.result { 47 | Some(r) => Ok(r), 48 | None => Err(SdkUtilError::JsonParse), 49 | } 50 | } 51 | 52 | /** 53 | Getting the result of a simple server response. 54 | */ 55 | pub fn handle_general_server_response(res: &str) -> Result<(), SdkUtilError> 56 | { 57 | handle_server_response::(res)?; 58 | 59 | Ok(()) 60 | } 61 | 62 | pub fn client_random_value_to_string(client_random_value: &impl ClientRandomValue) -> String 63 | { 64 | let out = client_random_value.prepare_export(); 65 | 66 | Base64::encode_string(out) 67 | } 68 | 69 | pub fn hashed_authentication_key_to_string(hashed_authentication_key_bytes: &impl HashedAuthenticationKey) -> String 70 | { 71 | let out = hashed_authentication_key_bytes.prepare_export(); 72 | 73 | Base64::encode_string(out) 74 | } 75 | 76 | pub fn derive_auth_key_for_auth_to_string(derive_auth_key_for_auth: &impl DeriveAuthKeyForAuth) -> String 77 | { 78 | let out = derive_auth_key_for_auth.prepare_export(); 79 | 80 | Base64::encode_string(out) 81 | } 82 | 83 | pub fn client_random_value_from_string(client_random_value: &str, alg: &str) -> Result 84 | { 85 | let v = Base64::decode_vec(client_random_value).map_err(|_| SdkUtilError::DecodeRandomValueFailed)?; 86 | //normally not needed only when the client needs to create the rand value, e.g.- for key update. 87 | Ok(C::from_bytes(v, alg)?) 88 | } 89 | 90 | /** 91 | Get the head and the data. 92 | 93 | This can not only be used internally, to get the used key_id 94 | */ 95 | #[cfg(feature = "encryption")] 96 | pub fn split_head_and_encrypted_data<'a, T: Deserialize<'a>>(data_with_head: &'a [u8]) -> Result<(T, &'a [u8]), SdkUtilError> 97 | { 98 | let mut i = 0usize; 99 | for data_itr in data_with_head { 100 | if *data_itr == 0u8 { 101 | //the mark to split the head from the data 102 | //found the ii where to split head from data 103 | break; 104 | } 105 | 106 | i += 1; 107 | } 108 | 109 | let head = serde_json::from_slice(&data_with_head[..i])?; 110 | 111 | //ignore the zero bytes 112 | Ok((head, &data_with_head[i + 1..])) 113 | } 114 | 115 | #[cfg(feature = "encryption")] 116 | pub fn put_head_and_encrypted_data(head: &T, encrypted: &[u8]) -> Result, SdkUtilError> 117 | { 118 | let head = serde_json::to_string(head).map_err(|_| SdkUtilError::JsonToStringFailed)?; 119 | 120 | let mut out = Vec::with_capacity(head.len() + 1 + encrypted.len()); 121 | 122 | out.extend_from_slice(head.as_bytes()); 123 | out.extend_from_slice(&[0u8]); 124 | out.extend_from_slice(encrypted); 125 | 126 | Ok(out) 127 | } 128 | 129 | pub fn import_key_from_pem(pem: &str) -> Result, SdkUtilError> 130 | { 131 | let (_type_label, data) = pem_rfc7468::decode_vec(pem.as_bytes()).map_err(|_| SdkUtilError::ImportingKeyFromPemFailed)?; 132 | 133 | Ok(data) 134 | } 135 | 136 | pub fn export_key_to_pem(key: &[u8]) -> Result 137 | { 138 | //export should not panic because we are creating the keys 139 | let key = pem_rfc7468::encode_string("PUBLIC KEY", LineEnding::default(), key).map_err(|_| SdkUtilError::ExportingPublicKeyFailed)?; 140 | 141 | Ok(key) 142 | } 143 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc_flutter" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | homepage.workspace = true 7 | authors.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | 11 | description = "The flutter implementation for sentc." 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [lib] 16 | name = "sentc_flutter" 17 | crate-type = ["staticlib", "cdylib"] 18 | 19 | [lints.rust] 20 | unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] } 21 | 22 | [dependencies] 23 | # own crypto lib 24 | sentc-crypto = { workspace = true, features = ["export", "full_rustls"] } 25 | 26 | sentc-crypto-common = { workspace = true } 27 | 28 | # flutter ffi 29 | flutter_rust_bridge = "=2.9.0" 30 | 31 | serde_json.workspace = true -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/flutter_rust_bridge.yaml: -------------------------------------------------------------------------------- 1 | rust_input: crate::api 2 | rust_root: . 3 | dart_output: ../sentc_flutter/sentc/lib/src/rust 4 | full_dep: true 5 | c_output: ../sentc_flutter/sentc/ios/Classes/frb.h 6 | duplicated_c_output: 7 | - ../sentc_flutter/sentc/macos/Classes/frb.h -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/scripts/build-android.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set up cargo-ndk 4 | #cargo install cargo-ndk 5 | #rustup target add \ 6 | # aarch64-linux-android \ 7 | # armv7-linux-androideabi \ 8 | # x86_64-linux-android \ 9 | # i686-linux-android 10 | 11 | cd .. 12 | 13 | # Build the android libraries in the jniLibs directory 14 | cargo ndk --manifest-path Cargo.toml \ 15 | -t armeabi-v7a \ 16 | -t arm64-v8a \ 17 | -t x86 \ 18 | -t x86_64 \ 19 | -o ../sentc_flutter/sentc/android/src/main/jniLibs \ 20 | build --release --package sentc_flutter 21 | 22 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/scripts/build-apple.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd .. 4 | 5 | # Build static libs 6 | for TARGET in \ 7 | aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim \ 8 | x86_64-apple-darwin aarch64-apple-darwin 9 | do 10 | #rustup target add $TARGET 11 | cargo build -r --target=$TARGET --package sentc_flutter 12 | done 13 | 14 | # Create XCFramework zip 15 | FRAMEWORK="Sentc.xcframework" 16 | LIBNAME=libsentc_flutter.a 17 | mkdir mac-lipo ios-sim-lipo 18 | IOS_SIM_LIPO=ios-sim-lipo/$LIBNAME 19 | MAC_LIPO=mac-lipo/$LIBNAME 20 | lipo -create -output $IOS_SIM_LIPO \ 21 | ../../../target/aarch64-apple-ios-sim/release/$LIBNAME \ 22 | ../../../target/x86_64-apple-ios/release/$LIBNAME 23 | lipo -create -output $MAC_LIPO \ 24 | ../../../target/aarch64-apple-darwin/release/$LIBNAME \ 25 | ../../../target/x86_64-apple-darwin/release/$LIBNAME 26 | xcodebuild -create-xcframework \ 27 | -library $IOS_SIM_LIPO \ 28 | -library $MAC_LIPO \ 29 | -library ../../../target/aarch64-apple-ios/release/$LIBNAME \ 30 | -output $FRAMEWORK 31 | 32 | zip -r $FRAMEWORK.zip $FRAMEWORK 33 | 34 | cp $FRAMEWORK.zip ../sentc_flutter/sentc/ios/Frameworks 35 | 36 | # Cleanup 37 | rm -rf ios-sim-lipo mac-lipo $FRAMEWORK $FRAMEWORK.zip 38 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/scripts/build-other.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd .. 4 | 5 | zig_build () { 6 | local TARGET="$1" 7 | local PLATFORM_NAME="$2" 8 | local LIBNAME="$3" 9 | #rustup target add "$TARGET" 10 | cargo zigbuild --target "$TARGET" -r --package sentc_flutter 11 | mkdir -p "../sentc_flutter/sentc/linux/$PLATFORM_NAME/" 12 | cp "../../../target/$TARGET/release/$LIBNAME" "../sentc_flutter/sentc/linux/$PLATFORM_NAME/" 13 | } 14 | 15 | win_build () { 16 | local TARGET="$1" 17 | local PLATFORM_NAME="$2" 18 | local LIBNAME="$3" 19 | #rustup target add "$TARGET" 20 | cargo xwin build --target "$TARGET" -r --package sentc_flutter 21 | mkdir -p "../sentc_flutter/sentc/windows/$PLATFORM_NAME/" 22 | cp "../../../target/$TARGET/release/$LIBNAME" "../sentc_flutter/sentc/windows/$PLATFORM_NAME/" 23 | } 24 | 25 | # Build all the dynamic libraries 26 | LINUX_LIBNAME=libsentc_flutter.so 27 | zig_build aarch64-unknown-linux-gnu linux-arm64 $LINUX_LIBNAME 28 | zig_build x86_64-unknown-linux-gnu linux-x64 $LINUX_LIBNAME 29 | 30 | WINDOWS_LIBNAME=sentc_flutter.dll 31 | #win_build aarch64-pc-windows-msvc windows-arm64 $WINDOWS_LIBNAME # windows arm is not supported by ring atm 32 | win_build x86_64-pc-windows-msvc windows-x64 $WINDOWS_LIBNAME -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/scripts/generate_code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # go to the main dir 4 | #cd ../../../../ 5 | cd .. 6 | 7 | flutter_rust_bridge_codegen generate \ 8 | --config-file flutter_rust_bridge.yaml 9 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/src/api/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod crypto; 2 | pub mod file; 3 | pub mod group; 4 | pub mod user; 5 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::too_many_arguments)] 2 | 3 | pub mod api; 4 | mod frb_generated; 5 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc_light_flutter" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | homepage.workspace = true 7 | authors.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | 11 | description = "The flutter implementation for sentc light." 12 | 13 | [lib] 14 | name = "sentc_light_flutter" 15 | crate-type = ["staticlib", "cdylib"] 16 | 17 | [lints.rust] 18 | unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] } 19 | 20 | [dependencies] 21 | # own crypto lib 22 | sentc-crypto-light = { workspace = true, features = ["export", "full_rustls"] } 23 | 24 | sentc-crypto-common = { workspace = true } 25 | 26 | flutter_rust_bridge = "=2.9.0" 27 | serde_json.workspace = true -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/flutter_rust_bridge.yaml: -------------------------------------------------------------------------------- 1 | rust_input: crate::api 2 | rust_root: . 3 | dart_output: ../sentc_flutter/sentc_light/lib/src/rust 4 | full_dep: true 5 | c_output: ../sentc_flutter/sentc_light/ios/Classes/frb.h 6 | duplicated_c_output: 7 | - ../sentc_flutter/sentc_light/macos/Classes/frb.h -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/scripts/build-android.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set up cargo-ndk 4 | #cargo install cargo-ndk 5 | #rustup target add \ 6 | # aarch64-linux-android \ 7 | # armv7-linux-androideabi \ 8 | # x86_64-linux-android \ 9 | # i686-linux-android 10 | 11 | cd .. 12 | 13 | # Build the android libraries in the jniLibs directory 14 | cargo ndk --manifest-path Cargo.toml \ 15 | -t armeabi-v7a \ 16 | -t arm64-v8a \ 17 | -t x86 \ 18 | -t x86_64 \ 19 | -o ../sentc_flutter/sentc_light/android/src/main/jniLibs \ 20 | build --release --package sentc_light_flutter 21 | 22 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/scripts/build-apple.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd .. 4 | 5 | # Build static libs 6 | for TARGET in \ 7 | aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim \ 8 | x86_64-apple-darwin aarch64-apple-darwin 9 | do 10 | #rustup target add $TARGET 11 | cargo build -r --target=$TARGET --package sentc_light_flutter 12 | done 13 | 14 | # Create XCFramework zip 15 | FRAMEWORK="SentcLight.xcframework" 16 | LIBNAME=libsentc_light_flutter.a 17 | mkdir mac-lipo ios-sim-lipo 18 | IOS_SIM_LIPO=ios-sim-lipo/$LIBNAME 19 | MAC_LIPO=mac-lipo/$LIBNAME 20 | lipo -create -output $IOS_SIM_LIPO \ 21 | ../../../target/aarch64-apple-ios-sim/release/$LIBNAME \ 22 | ../../../target/x86_64-apple-ios/release/$LIBNAME 23 | lipo -create -output $MAC_LIPO \ 24 | ../../../target/aarch64-apple-darwin/release/$LIBNAME \ 25 | ../../../target/x86_64-apple-darwin/release/$LIBNAME 26 | xcodebuild -create-xcframework \ 27 | -library $IOS_SIM_LIPO \ 28 | -library $MAC_LIPO \ 29 | -library ../../../target/aarch64-apple-ios/release/$LIBNAME \ 30 | -output $FRAMEWORK 31 | 32 | zip -r $FRAMEWORK.zip $FRAMEWORK 33 | 34 | cp $FRAMEWORK.zip ../sentc_flutter/sentc_light/ios/Frameworks 35 | 36 | # Cleanup 37 | rm -rf ios-sim-lipo mac-lipo $FRAMEWORK $FRAMEWORK.zip 38 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/scripts/build-other.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd .. 4 | 5 | zig_build () { 6 | local TARGET="$1" 7 | local PLATFORM_NAME="$2" 8 | local LIBNAME="$3" 9 | #rustup target add "$TARGET" 10 | cargo zigbuild --target "$TARGET" -r --package sentc_light_flutter 11 | mkdir -p "../sentc_flutter/sentc_light/linux/$PLATFORM_NAME/" 12 | cp "../../../target/$TARGET/release/$LIBNAME" "../sentc_flutter/sentc_light/linux/$PLATFORM_NAME/" 13 | } 14 | 15 | win_build () { 16 | local TARGET="$1" 17 | local PLATFORM_NAME="$2" 18 | local LIBNAME="$3" 19 | #rustup target add "$TARGET" 20 | cargo xwin build --target "$TARGET" -r --package sentc_light_flutter 21 | mkdir -p "../sentc_flutter/sentc_light/windows/$PLATFORM_NAME/" 22 | cp "../../../target/$TARGET/release/$LIBNAME" "../sentc_flutter/sentc_light/windows/$PLATFORM_NAME/" 23 | } 24 | 25 | # Build all the dynamic libraries 26 | LINUX_LIBNAME=libsentc_light_flutter.so 27 | zig_build aarch64-unknown-linux-gnu linux-arm64 $LINUX_LIBNAME 28 | zig_build x86_64-unknown-linux-gnu linux-x64 $LINUX_LIBNAME 29 | 30 | WINDOWS_LIBNAME=sentc_light_flutter.dll 31 | #win_build aarch64-pc-windows-msvc windows-arm64 $WINDOWS_LIBNAME # windows arm is not supported by ring atm 32 | win_build x86_64-pc-windows-msvc windows-x64 $WINDOWS_LIBNAME -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/scripts/generate_code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # go to the main dir 4 | #cd ../../../../ 5 | cd .. 6 | 7 | flutter_rust_bridge_codegen generate \ 8 | --config-file flutter_rust_bridge.yaml 9 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/src/api/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod group; 2 | pub mod user; 3 | -------------------------------------------------------------------------------- /implementation/dart/sentc_flutter_rust_light/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::too_many_arguments)] 2 | 3 | pub mod api; 4 | mod frb_generated; 5 | -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # Log files 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | 13 | # nyc test coverage 14 | .nyc_output -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc_wasm" 3 | version = "0.15.0" 4 | edition = "2021" 5 | 6 | description = "Wasm for sentc. End-to-end encryption sdk" 7 | license-file = "LICENSE" 8 | authors = ["Sentclose ", "Jörn Heinemann "] 9 | homepage = "https://sentc.com/" 10 | documentation = "https://sentc.com/" 11 | repository = "https://github.com/sentclose/sentc" 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [lib] 16 | crate-type = ["cdylib"] 17 | 18 | [dependencies] 19 | # own crypto lib 20 | sentc-crypto = { workspace = true, features = ["export", "full_wasm"] } 21 | 22 | sentc-crypto-common = { workspace = true } 23 | 24 | # must be js feature for wasm 25 | getrandom = { version = "0.2", features = ["js"] } 26 | 27 | # wasm dep 28 | wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"] } 29 | js-sys = "0.3.58" 30 | 31 | # sha2 with non std 32 | sha2 = { version = "0.10", default-features = false } 33 | 34 | wasm-bindgen-futures = "0.4.31" 35 | 36 | serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "chrome": 80 8 | } 9 | } 10 | ] 11 | ], 12 | "plugins": ["@babel/plugin-transform-modules-commonjs"] 13 | } -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sentc_wasm", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "babel_node": "babel pkg/sentc_wasm.js --out-file pkg/sentc_wasm_cjs.js --plugins babel-plugin-transform-import-meta", 8 | "babel_browser": "babel pkg/sentc_wasm.js --out-file pkg/sentc_wasm_bjs.js", 9 | "babel": "npm run babel_browser && npm run babel_node" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "@babel/cli": "^7.18.10", 16 | "@babel/core": "^7.18.10", 17 | "@babel/plugin-transform-modules-commonjs": "^7.18.6", 18 | "@babel/preset-env": "^7.18.10", 19 | "babel-plugin-transform-import-meta": "^2.2.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/pkg/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !package.json -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sentc_wasm", 3 | "collaborators": [ 4 | "Sentclose ", 5 | "Jörn Heinemann " 6 | ], 7 | "description": "Wasm for sentc. End-to-end encryption sdk", 8 | "version": "0.15.0", 9 | "license": "AGPL-3.0", 10 | "files": [ 11 | "sentc_wasm_cjs.js", 12 | "sentc_wasm_bjs.js", 13 | "sentc_wasm_bg.wasm", 14 | "sentc_wasm.js", 15 | "sentc_wasm.d.ts", 16 | "LICENSE" 17 | ], 18 | "main": "sentc_wasm_cjs.js", 19 | "browser": "sentc_wasm_bjs.js", 20 | "module": "sentc_wasm.js", 21 | "types": "sentc_wasm.d.ts", 22 | "sideEffects": false 23 | } -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![allow(clippy::too_many_arguments, deprecated)] 3 | 4 | pub mod crypto; 5 | pub mod file; 6 | pub mod group; 7 | pub mod user; 8 | pub mod util; 9 | 10 | extern crate alloc; 11 | -------------------------------------------------------------------------------- /implementation/js/sentc_wasm/src/util.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | 3 | use wasm_bindgen::prelude::*; 4 | use wasm_bindgen::JsValue; 5 | 6 | #[wasm_bindgen] 7 | pub struct Claims 8 | { 9 | aud: String, 10 | sub: String, //the app id 11 | exp: usize, 12 | iat: usize, 13 | fresh: bool, //was this token from refresh jwt or from login 14 | } 15 | 16 | #[wasm_bindgen] 17 | impl Claims 18 | { 19 | pub fn get_aud(&self) -> String 20 | { 21 | self.aud.clone() 22 | } 23 | 24 | pub fn get_sub(&self) -> String 25 | { 26 | self.sub.clone() 27 | } 28 | 29 | pub fn get_exp(&self) -> usize 30 | { 31 | self.exp 32 | } 33 | 34 | pub fn get_iat(&self) -> usize 35 | { 36 | self.iat 37 | } 38 | 39 | pub fn get_fresh(&self) -> bool 40 | { 41 | self.fresh 42 | } 43 | } 44 | 45 | impl From for Claims 46 | { 47 | fn from(claims: sentc_crypto_common::user::Claims) -> Self 48 | { 49 | Self { 50 | aud: claims.aud, 51 | sub: claims.sub, 52 | exp: claims.exp, 53 | iat: claims.iat, 54 | fresh: claims.fresh, 55 | } 56 | } 57 | } 58 | 59 | #[wasm_bindgen] 60 | pub fn decode_jwt(jwt: &str) -> Result 61 | { 62 | let claims = sentc_crypto::util_req_full::decode_jwt(jwt)?; 63 | 64 | Ok(claims.into()) 65 | } 66 | -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # Log files 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | 13 | # nyc test coverage 14 | .nyc_output -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentc_wasm_light" 3 | version = "0.13.0" 4 | edition = "2021" 5 | 6 | description = "Wasm for sentc. End-to-end encryption sdk light" 7 | license-file = "LICENSE" 8 | authors = ["Sentclose ", "Jörn Heinemann "] 9 | homepage = "https://sentc.com/" 10 | documentation = "https://sentc.com/" 11 | repository = "https://github.com/sentclose/sentc" 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [lib] 16 | crate-type = ["cdylib"] 17 | 18 | [dependencies] 19 | sentc-crypto-common = { workspace = true } 20 | sentc-crypto-light = { workspace = true, features = ["export", "full_wasm"] } 21 | 22 | # must be js feature for wasm 23 | getrandom = { version = "0.2", features = ["js"] } 24 | 25 | # wasm dep 26 | wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"] } 27 | js-sys = "0.3.58" 28 | 29 | # sha2 with non std 30 | sha2 = { version = "0.10", default-features = false } 31 | 32 | wasm-bindgen-futures = "0.4.31" 33 | 34 | serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "chrome": 80 8 | } 9 | } 10 | ] 11 | ], 12 | "plugins": ["@babel/plugin-transform-modules-commonjs"] 13 | } -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sentc_wasm_light", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "babel_node": "babel pkg/sentc_wasm_light.js --out-file pkg/sentc_wasm_light_cjs.js --plugins babel-plugin-transform-import-meta", 8 | "babel_browser": "babel pkg/sentc_wasm_light.js --out-file pkg/sentc_wasm_light_bjs.js", 9 | "babel": "npm run babel_browser && npm run babel_node" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@babel/cli": "^7.18.10", 15 | "@babel/core": "^7.18.10", 16 | "@babel/plugin-transform-modules-commonjs": "^7.18.6", 17 | "@babel/preset-env": "^7.18.10", 18 | "babel-plugin-transform-import-meta": "^2.2.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/pkg/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !package.json -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sentc_wasm_light", 3 | "collaborators": [ 4 | "Sentclose ", 5 | "Jörn Heinemann " 6 | ], 7 | "description": "Wasm for sentc. End-to-end encryption sdk light", 8 | "version": "0.13.0", 9 | "license": "AGPL-3.0", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/sentclose/sentc" 13 | }, 14 | "files": [ 15 | "sentc_wasm_light_cjs.js", 16 | "sentc_wasm_light_light.js", 17 | "sentc_wasm_light_bg.wasm", 18 | "sentc_wasm_light.js", 19 | "sentc_wasm_light.d.ts" 20 | ], 21 | "module": "sentc_wasm_light.js", 22 | "homepage": "https://sentc.com/", 23 | "types": "sentc_wasm_light.d.ts", 24 | "sideEffects": false 25 | } -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![allow(clippy::too_many_arguments, deprecated)] 3 | 4 | pub mod group; 5 | pub mod user; 6 | pub mod util; 7 | 8 | extern crate alloc; 9 | -------------------------------------------------------------------------------- /implementation/js/sentc_wasm_light/src/util.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | 3 | use sentc_crypto_light::util_req_full; 4 | use wasm_bindgen::prelude::*; 5 | use wasm_bindgen::JsValue; 6 | 7 | #[wasm_bindgen] 8 | pub struct Claims 9 | { 10 | aud: String, 11 | sub: String, //the app id 12 | exp: usize, 13 | iat: usize, 14 | fresh: bool, //was this token from refresh jwt or from login 15 | } 16 | 17 | #[wasm_bindgen] 18 | impl Claims 19 | { 20 | pub fn get_aud(&self) -> String 21 | { 22 | self.aud.clone() 23 | } 24 | 25 | pub fn get_sub(&self) -> String 26 | { 27 | self.sub.clone() 28 | } 29 | 30 | pub fn get_exp(&self) -> usize 31 | { 32 | self.exp 33 | } 34 | 35 | pub fn get_iat(&self) -> usize 36 | { 37 | self.iat 38 | } 39 | 40 | pub fn get_fresh(&self) -> bool 41 | { 42 | self.fresh 43 | } 44 | } 45 | 46 | impl From for Claims 47 | { 48 | fn from(claims: sentc_crypto_common::user::Claims) -> Self 49 | { 50 | Self { 51 | aud: claims.aud, 52 | sub: claims.sub, 53 | exp: claims.exp, 54 | iat: claims.iat, 55 | fresh: claims.fresh, 56 | } 57 | } 58 | } 59 | 60 | #[wasm_bindgen] 61 | pub fn decode_jwt(jwt: &str) -> Result 62 | { 63 | let claims = util_req_full::decode_jwt(jwt)?; 64 | 65 | Ok(claims.into()) 66 | } 67 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.aarch64-unknown-linux-musl] 2 | linker = "aarch64-linux-musl-gcc" 3 | rustflags = ["-C", "target-feature=-crt-static"] 4 | [target.x86_64-pc-windows-msvc] 5 | rustflags = ["-C", "target-feature=+crt-static"] -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/node 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # TypeScript v1 declaration files 49 | typings/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variables file 76 | .env 77 | .env.test 78 | 79 | # parcel-bundler cache (https://parceljs.org/) 80 | .cache 81 | 82 | # Next.js build output 83 | .next 84 | 85 | # Nuxt.js build / generate output 86 | .nuxt 87 | dist 88 | 89 | # Gatsby files 90 | .cache/ 91 | # Comment in the public line in if your project uses Gatsby and not Next.js 92 | # https://nextjs.org/blog/next-9-1#public-directory-support 93 | # public 94 | 95 | # vuepress build output 96 | .vuepress/dist 97 | 98 | # Serverless directories 99 | .serverless/ 100 | 101 | # FuseBox cache 102 | .fusebox/ 103 | 104 | # DynamoDB Local files 105 | .dynamodb/ 106 | 107 | # TernJS port file 108 | .tern-port 109 | 110 | # Stores VSCode versions used for testing VSCode extensions 111 | .vscode-test 112 | 113 | # End of https://www.toptal.com/developers/gitignore/api/node 114 | 115 | # Created by https://www.toptal.com/developers/gitignore/api/macos 116 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos 117 | 118 | ### macOS ### 119 | # General 120 | .DS_Store 121 | .AppleDouble 122 | .LSOverride 123 | 124 | # Icon must end with two 125 | Icon 126 | 127 | 128 | # Thumbnails 129 | ._* 130 | 131 | # Files that might appear in the root of a volume 132 | .DocumentRevisions-V100 133 | .fseventsd 134 | .Spotlight-V100 135 | .TemporaryItems 136 | .Trashes 137 | .VolumeIcon.icns 138 | .com.apple.timemachine.donotpresent 139 | 140 | # Directories potentially created on remote AFP share 141 | .AppleDB 142 | .AppleDesktop 143 | Network Trash Folder 144 | Temporary Items 145 | .apdisk 146 | 147 | ### macOS Patch ### 148 | # iCloud generated files 149 | *.icloud 150 | 151 | # End of https://www.toptal.com/developers/gitignore/api/macos 152 | 153 | # Created by https://www.toptal.com/developers/gitignore/api/windows 154 | # Edit at https://www.toptal.com/developers/gitignore?templates=windows 155 | 156 | ### Windows ### 157 | # Windows thumbnail cache files 158 | Thumbs.db 159 | Thumbs.db:encryptable 160 | ehthumbs.db 161 | ehthumbs_vista.db 162 | 163 | # Dump file 164 | *.stackdump 165 | 166 | # Folder config file 167 | [Dd]esktop.ini 168 | 169 | # Recycle Bin used on file shares 170 | $RECYCLE.BIN/ 171 | 172 | # Windows Installer files 173 | *.cab 174 | *.msi 175 | *.msix 176 | *.msm 177 | *.msp 178 | 179 | # Windows shortcuts 180 | *.lnk 181 | 182 | # End of https://www.toptal.com/developers/gitignore/api/windows 183 | 184 | #Added by cargo 185 | 186 | /target 187 | 188 | .pnp.* 189 | .yarn/* 190 | !.yarn/patches 191 | !.yarn/plugins 192 | !.yarn/releases 193 | !.yarn/sdks 194 | !.yarn/versions 195 | 196 | *.node 197 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !index.d.ts 3 | !index.js 4 | !LICENSE 5 | !package.json -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sentclose_sentc_node_js" 3 | version.workspace = true 4 | edition.workspace = true 5 | license-file.workspace = true 6 | authors.workspace = true 7 | homepage.workspace = true 8 | documentation.workspace = true 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | description = "The node js implementation for sentc." 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [dependencies] 18 | # own crypto lib 19 | sentc-crypto = { workspace = true, features = ["export", "full_rustls"] } 20 | 21 | sentc-crypto-common = { workspace = true } 22 | 23 | # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix 24 | napi = { version = "2.12.2", default-features = false, features = ["napi4", "tokio_rt"] } 25 | napi-derive = "2.12.2" 26 | 27 | [build-dependencies] 28 | napi-build = "2.0.1" -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/build.rs: -------------------------------------------------------------------------------- 1 | extern crate napi_build; 2 | 3 | fn main() { 4 | napi_build::setup(); 5 | } 6 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for TARGET in \ 4 | x86_64-apple-darwin aarch64-apple-darwin \ 5 | x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu #\ 6 | #x86_64-unknown-linux-musl aarch64-unknown-linux-musl 7 | do 8 | #rustup target add $TARGET 9 | yarn exec napi build --platform --release --target=$TARGET 10 | done 11 | 12 | yarn exec napi artifacts -d . -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/darwin-arm64/README.md: -------------------------------------------------------------------------------- 1 | # `@sentclose/sentc_node_js-darwin-arm64` 2 | 3 | This is the **aarch64-apple-darwin** binary for `@sentclose/sentc_node_js` 4 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/darwin-arm64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sentclose/sentc_node_js-darwin-arm64", 3 | "version": "0.15.0", 4 | "os": [ 5 | "darwin" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "sentc_node_js.darwin-arm64.node", 11 | "files": [ 12 | "sentc_node_js.darwin-arm64.node" 13 | ], 14 | "license": "AGPL-3.0", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/darwin-x64/README.md: -------------------------------------------------------------------------------- 1 | # `@sentclose/sentc_node_js-darwin-x64` 2 | 3 | This is the **x86_64-apple-darwin** binary for `@sentclose/sentc_node_js` 4 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/darwin-x64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sentclose/sentc_node_js-darwin-x64", 3 | "version": "0.15.0", 4 | "os": [ 5 | "darwin" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "sentc_node_js.darwin-x64.node", 11 | "files": [ 12 | "sentc_node_js.darwin-x64.node" 13 | ], 14 | "license": "AGPL-3.0", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/linux-arm64-gnu/README.md: -------------------------------------------------------------------------------- 1 | # `@sentclose/sentc_node_js-linux-arm64-gnu` 2 | 3 | This is the **aarch64-unknown-linux-gnu** binary for `@sentclose/sentc_node_js` 4 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/linux-arm64-gnu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sentclose/sentc_node_js-linux-arm64-gnu", 3 | "version": "0.15.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "sentc_node_js.linux-arm64-gnu.node", 11 | "files": [ 12 | "sentc_node_js.linux-arm64-gnu.node" 13 | ], 14 | "license": "AGPL-3.0", 15 | "engines": { 16 | "node": ">= 10" 17 | }, 18 | "libc": [ 19 | "glibc" 20 | ] 21 | } -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/linux-arm64-musl/README.md: -------------------------------------------------------------------------------- 1 | # `@sentclose/sentc_node_js-linux-arm64-musl` 2 | 3 | This is the **aarch64-unknown-linux-musl** binary for `@sentclose/sentc_node_js` 4 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/linux-arm64-musl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sentclose/sentc_node_js-linux-arm64-musl", 3 | "version": "0.15.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "sentc_node_js.linux-arm64-musl.node", 11 | "files": [ 12 | "sentc_node_js.linux-arm64-musl.node" 13 | ], 14 | "license": "AGPL-3.0", 15 | "engines": { 16 | "node": ">= 10" 17 | }, 18 | "libc": [ 19 | "musl" 20 | ] 21 | } -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/linux-x64-gnu/README.md: -------------------------------------------------------------------------------- 1 | # `@sentclose/sentc_node_js-linux-x64-gnu` 2 | 3 | This is the **x86_64-unknown-linux-gnu** binary for `@sentclose/sentc_node_js` 4 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/linux-x64-gnu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sentclose/sentc_node_js-linux-x64-gnu", 3 | "version": "0.15.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "sentc_node_js.linux-x64-gnu.node", 11 | "files": [ 12 | "sentc_node_js.linux-x64-gnu.node" 13 | ], 14 | "license": "AGPL-3.0", 15 | "engines": { 16 | "node": ">= 10" 17 | }, 18 | "libc": [ 19 | "glibc" 20 | ] 21 | } -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/win32-x64-msvc/README.md: -------------------------------------------------------------------------------- 1 | # `@sentclose/sentc_node_js-win32-x64-msvc` 2 | 3 | This is the **x86_64-pc-windows-msvc** binary for `@sentclose/sentc_node_js` 4 | -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/npm/win32-x64-msvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sentclose/sentc_node_js-win32-x64-msvc", 3 | "version": "0.15.0", 4 | "os": [ 5 | "win32" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "sentc_node_js.win32-x64-msvc.node", 11 | "files": [ 12 | "sentc_node_js.win32-x64-msvc.node" 13 | ], 14 | "license": "AGPL-3.0", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sentclose/sentc_node_js", 3 | "version": "0.15.0", 4 | "main": "index.js", 5 | "types": "index.d.ts", 6 | "napi": { 7 | "name": "sentc_node_js", 8 | "triples": { 9 | "additional": [ 10 | "aarch64-apple-darwin", 11 | "aarch64-unknown-linux-gnu", 12 | "aarch64-unknown-linux-musl" 13 | ] 14 | } 15 | }, 16 | "license": "AGPL-3", 17 | "devDependencies": { 18 | "@napi-rs/cli": "^2.18.4", 19 | "ava": "^6.0.1" 20 | }, 21 | "ava": { 22 | "timeout": "3m" 23 | }, 24 | "engines": { 25 | "node": ">= 10" 26 | }, 27 | "scripts": { 28 | "artifacts": "napi artifacts", 29 | "build": "napi build --platform --release", 30 | "build:debug": "napi build --platform", 31 | "prepublishOnly": "napi prepublish -t npm", 32 | "test": "ava", 33 | "universal": "napi universal", 34 | "version": "napi version" 35 | }, 36 | "files": [ 37 | "index.d.ts", 38 | "index.js", 39 | "LICENSE" 40 | ], 41 | "packageManager": "yarn@4.9.1", 42 | "optionalDependencies": { 43 | "@sentclose/sentc_node_js-win32-x64-msvc": "0.15.0", 44 | "@sentclose/sentc_node_js-darwin-x64": "0.15.0", 45 | "@sentclose/sentc_node_js-linux-x64-gnu": "0.15.0", 46 | "@sentclose/sentc_node_js-darwin-arm64": "0.15.0", 47 | "@sentclose/sentc_node_js-linux-arm64-gnu": "0.15.0", 48 | "@sentclose/sentc_node_js-linux-arm64-musl": "0.15.0" 49 | } 50 | } -------------------------------------------------------------------------------- /implementation/nodejs/sentc_node_js_rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | //#![deny(clippy::all)] 2 | #![allow(clippy::too_many_arguments)] 3 | 4 | mod crypto; 5 | mod file; 6 | mod group; 7 | mod user; 8 | 9 | #[macro_use] 10 | extern crate napi_derive; 11 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # https://github.com/rust-lang/rustfmt/blob/master/Configurations.md 2 | # install: rustup component add rustfmt --toolchain nightly 3 | # use: cargo +nightly fmt 4 | 5 | unstable_features = true 6 | 7 | hard_tabs = true 8 | newline_style = "Unix" 9 | binop_separator = "Back" 10 | blank_lines_upper_bound = 1 11 | brace_style = "AlwaysNextLine" 12 | control_brace_style = "AlwaysSameLine" 13 | combine_control_expr = false 14 | empty_item_single_line = true 15 | enum_discrim_align_threshold = 0 16 | fn_args_layout = "Tall" 17 | fn_single_line = false 18 | force_multiline_blocks = true 19 | format_macro_bodies = true 20 | 21 | max_width = 150 22 | chain_width = 60 23 | struct_lit_width=18 24 | fn_call_width = 70 25 | 26 | # imports 27 | imports_indent = "Block" 28 | imports_layout = "HorizontalVertical" 29 | reorder_imports = true 30 | group_imports = "StdExternalCrate" 31 | 32 | indent_style = "Block" 33 | inline_attribute_width = 0 34 | match_arm_blocks = true 35 | match_block_trailing_comma = true 36 | merge_derives = true 37 | imports_granularity = "Module" 38 | overflow_delimited_expr = false 39 | remove_nested_parens = true 40 | #reorder_impl_items = true 41 | reorder_modules = true 42 | short_array_element_width_threshold = 10 43 | space_after_colon = true 44 | space_before_colon = false 45 | struct_field_align_threshold = 0 46 | struct_lit_single_line = false 47 | 48 | trailing_comma = "Vertical" 49 | trailing_semicolon = true 50 | 51 | type_punctuation_density = "Wide" 52 | 53 | #use_try_shorthand = true 54 | 55 | where_single_line = false 56 | --------------------------------------------------------------------------------