├── rust-toolchain ├── .cargo └── config.toml ├── .gitignore ├── wasm-libs ├── libaes.a ├── build.zig.zon ├── build.zig └── aes.zig ├── .github └── workflows │ └── issues.yml ├── Cargo.toml ├── LICENSE ├── src ├── cmac_aes128.rs ├── lib.rs ├── aes128ctr.rs ├── aes256ctr.rs ├── aes128cbc.rs ├── aes256cbc.rs ├── aegis256.rs ├── aes128gcm.rs ├── aes128ocb.rs ├── aes256gcm.rs ├── aes256ocb.rs ├── aegis128l.rs ├── aegis128x2.rs ├── aegis128x4.rs ├── aegis256x2.rs └── aegis256x4.rs ├── README.md └── benches └── benchmark.rs /rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | targets = ["wasm32-wasip1"] 3 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.wasm32-wasip1] 2 | runner = "wasmer" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .zig-cache 3 | zig-out 4 | target 5 | Cargo.lock 6 | -------------------------------------------------------------------------------- /wasm-libs/libaes.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedisct1/rust-aes-wasm/HEAD/wasm-libs/libaes.a -------------------------------------------------------------------------------- /wasm-libs/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = .wasm_libs, 3 | 4 | .version = "0.0.0", 5 | 6 | .fingerprint = 0x1512050883ac07d4, 7 | 8 | .dependencies = .{ 9 | .cbc = .{ 10 | .url = "https://github.com/jedisct1/zig-cbc/archive/refs/tags/0.1.2.tar.gz", 11 | .hash = "122050482956917066c64d32b571ae80f7291fa5c5a12ecf05e5a0bf65600eff4d65", 12 | }, 13 | }, 14 | .paths = .{ 15 | "build.zig", 16 | "build.zig.zon", 17 | "aes.zig", 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/issues.yml: -------------------------------------------------------------------------------- 1 | name: Close inactive issues 2 | on: 3 | schedule: 4 | - cron: "30 1 * * *" 5 | 6 | jobs: 7 | close-issues: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | steps: 13 | - uses: actions/stale@v9 14 | with: 15 | stale-issue-message: "This issue is stale because it has been open for 30 days with no activity." 16 | close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." 17 | repo-token: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aes-wasm" 3 | version = "0.1.17" 4 | edition = "2021" 5 | readme = "README.md" 6 | license = "MIT" 7 | repository = "https://github.com/jedisct1/rust-aes-wasm" 8 | authors = ["Frank Denis "] 9 | description = "AES-GCM, AES-OCB, AEGIS, AES-CTR, CMAC-AES for WebAssembly" 10 | keywords = ["aes-gcm", "aes-ctr", "cmac", "wasm", "webassembly"] 11 | 12 | [dev-dependencies] 13 | benchmark-simple = "0.1.10" 14 | aegis = "0.9.0" 15 | aes-gcm = "0.10.3" 16 | cmac = "0.7.2" 17 | ctr = "0.9.2" 18 | cbc = "0.1.2" 19 | 20 | [[bench]] 21 | name = "benchmark" 22 | harness = false 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2025 Frank Denis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /wasm-libs/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.Build) void { 4 | const target = b.standardTargetOptions(.{ 5 | .default_target = .{ 6 | .cpu_arch = .wasm32, 7 | .os_tag = .wasi, 8 | .cpu_features_add = std.Target.wasm.featureSet(&.{ .simd128, .bulk_memory }), 9 | }, 10 | }); 11 | const optimize = b.standardOptimizeOption(.{ 12 | .preferred_optimize_mode = .ReleaseFast, 13 | }); 14 | 15 | const cbc = b.dependency("cbc", .{ 16 | .target = target, 17 | .optimize = optimize, 18 | }); 19 | 20 | const lib = b.addStaticLibrary(.{ 21 | .name = "aes", 22 | .root_source_file = b.path("aes.zig"), 23 | .target = target, 24 | .optimize = optimize, 25 | .strip = true, 26 | }); 27 | lib.root_module.addImport("cbc", cbc.module("cbc")); 28 | lib.linkLibrary(cbc.artifact("cbc")); 29 | b.installArtifact(lib); 30 | 31 | const exe = b.addExecutable(.{ 32 | .name = "aes", 33 | .root_source_file = b.path("aes.zig"), 34 | .target = target, 35 | .optimize = optimize, 36 | .strip = true, 37 | }); 38 | exe.rdynamic = true; 39 | exe.wasi_exec_model = .reactor; 40 | exe.entry = .disabled; 41 | exe.root_module.addImport("cbc", cbc.module("cbc")); 42 | exe.linkLibrary(cbc.artifact("cbc")); 43 | b.installArtifact(exe); 44 | } 45 | -------------------------------------------------------------------------------- /src/cmac_aes128.rs: -------------------------------------------------------------------------------- 1 | //! CMAC-AES-128 message authentication code for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides message authentication using AES-128 as a MAC (Cipher-based Message Authentication Code). 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::cmac_aes128::{mac, Key}; 8 | //! let key = Key::default(); 9 | //! let msg = b"hello"; 10 | //! let tag = mac(msg, &key); 11 | //! ``` 12 | 13 | mod zig { 14 | extern "C" { 15 | pub fn cmac_aes128(tag: *mut u8, m: *const u8, m_len: usize, k: *const u8) -> i32; 16 | } 17 | } 18 | 19 | pub use crate::*; 20 | 21 | /// The length of the key in bytes. 22 | /// 23 | /// This constant is used for key array sizing. 24 | pub const KEY_LEN: usize = 16; 25 | /// The length of the authentication tag in bytes. 26 | /// 27 | /// This constant is used for tag array sizing. 28 | pub const TAG_LEN: usize = 16; 29 | 30 | /// Key type for CMAC-AES128 (16 bytes). 31 | pub type Key = [u8; KEY_LEN]; 32 | /// Tag type for CMAC-AES128 (16 bytes). 33 | pub type Tag = [u8; TAG_LEN]; 34 | 35 | /// Computes the CMAC (Cipher-based Message Authentication Code) for a message using AES-128. 36 | /// 37 | /// # Arguments 38 | /// * `msg` - The message to authenticate. 39 | /// * `key` - Reference to the secret key. 40 | /// 41 | /// # Returns 42 | /// Authentication tag as a 16-byte array. 43 | /// 44 | /// # Example 45 | /// ``` 46 | /// use aes_wasm::cmac_aes128::{mac, Key}; 47 | /// let key = Key::default(); 48 | /// let msg = b"hello"; 49 | /// let tag = mac(msg, &key); 50 | /// ``` 51 | pub fn mac(msg: impl AsRef<[u8]>, key: &Key) -> Tag { 52 | let msg = msg.as_ref(); 53 | let mut tag = Tag::default(); 54 | unsafe { 55 | zig::cmac_aes128(tag.as_mut_ptr(), msg.as_ptr(), msg.len(), key.as_ptr()); 56 | }; 57 | tag 58 | } 59 | 60 | #[cfg(test)] 61 | mod test { 62 | use super::*; 63 | 64 | #[test] 65 | fn cmac_aes128() { 66 | let key = Key::default(); 67 | let msg = b"hello world"; 68 | _ = mac(msg, &key); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # aes-wasm 2 | //! 3 | //! High-performance AEAD, stream cipher, and MAC primitives for WebAssembly/WASI. 4 | //! 5 | //! This crate provides a simple, dependency-free API for cryptography in WASI environments. 6 | //! 7 | //! ## Example: AES-128-GCM 8 | //! ```rust 9 | //! use aes_wasm::aes128gcm::{encrypt, decrypt, Key, Nonce}; 10 | //! let key = Key::default(); 11 | //! let nonce = Nonce::default(); 12 | //! let msg = b"hello world"; 13 | //! let ad = b"extra data"; 14 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 15 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 16 | //! assert_eq!(plaintext, msg); 17 | //! ``` 18 | //! 19 | //! AEAD ciphers for WebAssembly, including AEGIS, AES-GCM, AES-OCB, AES-CBC, AES-CTR, and CMAC. 20 | //! 21 | //! This crate provides high-performance AEAD and MAC primitives for use in WebAssembly environments. 22 | //! It exposes a simple API for encryption, decryption, and authentication using modern ciphers. 23 | //! 24 | //! # Example 25 | //! ``` 26 | //! use aes_wasm::aes128gcm::{encrypt, decrypt, Key, Nonce}; 27 | //! let key = Key::default(); 28 | //! let nonce = Nonce::default(); 29 | //! let msg = b"hello"; 30 | //! let ad = b"ad"; 31 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 32 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 33 | //! assert_eq!(plaintext, msg); 34 | //! ``` 35 | 36 | use core::fmt::{self, Display}; 37 | 38 | /// Error type for AEAD operations. 39 | /// 40 | /// This error is returned when authentication fails during decryption. 41 | /// 42 | /// # Example 43 | /// ``` 44 | /// use aes_wasm::aes128gcm::{decrypt, Key, Nonce}; 45 | /// use aes_wasm::Error; 46 | /// let key = Key::default(); 47 | /// let nonce = Nonce::default(); 48 | /// let ad = b"ad"; 49 | /// // Intentionally use invalid ciphertext 50 | /// let ciphertext = b"invalid"; 51 | /// let result = decrypt(ciphertext, ad, &key, nonce); 52 | /// assert_eq!(result, Err(Error::VerificationFailed)); 53 | /// ``` 54 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 55 | pub enum Error { 56 | /// Ciphertext verification failed. 57 | VerificationFailed, 58 | } 59 | 60 | impl std::error::Error for Error {} 61 | 62 | impl Display for Error { 63 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 64 | match self { 65 | Error::VerificationFailed => write!(f, "Verification failed"), 66 | } 67 | } 68 | } 69 | 70 | pub mod aegis128l; 71 | pub mod aegis128x2; 72 | pub mod aegis128x4; 73 | pub mod aegis256; 74 | pub mod aegis256x2; 75 | pub mod aegis256x4; 76 | pub mod aes128cbc; 77 | pub mod aes128ctr; 78 | pub mod aes128gcm; 79 | pub mod aes128ocb; 80 | pub mod aes256cbc; 81 | pub mod aes256ctr; 82 | pub mod aes256gcm; 83 | pub mod aes256ocb; 84 | pub mod cmac_aes128; 85 | -------------------------------------------------------------------------------- /src/aes128ctr.rs: -------------------------------------------------------------------------------- 1 | //! AES-128-CTR stream cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides encryption and decryption using AES-128 in CTR mode. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes128ctr::{encrypt, decrypt, Key, IV}; 8 | //! let key = Key::default(); 9 | //! let iv = IV::default(); 10 | //! let msg = b"hello"; 11 | //! let ciphertext = encrypt(msg, &key, iv); 12 | //! let plaintext = decrypt(ciphertext, &key, iv); 13 | //! assert_eq!(plaintext, msg); 14 | //! ``` 15 | 16 | mod zig { 17 | extern "C" { 18 | pub fn aes128ctr( 19 | c: *mut u8, 20 | c_len: usize, 21 | m: *const u8, 22 | m_len: usize, 23 | iv: *const u8, 24 | k: *const u8, 25 | ) -> i32; 26 | } 27 | } 28 | 29 | pub use crate::*; 30 | 31 | /// The length of the key in bytes. 32 | /// 33 | /// This constant is used for key array sizing. 34 | pub const KEY_LEN: usize = 16; 35 | /// The length of the IV in bytes. 36 | /// 37 | /// This constant is used for IV array sizing. 38 | pub const IV_LEN: usize = 16; 39 | 40 | /// Key type for AES-128-CTR (16 bytes). 41 | pub type Key = [u8; KEY_LEN]; 42 | /// IV type for AES-128-CTR (16 bytes). 43 | pub type IV = [u8; IV_LEN]; 44 | 45 | /// Encrypts a message using AES-128 in CTR mode. 46 | /// 47 | /// # Arguments 48 | /// * `msg` - The plaintext message to encrypt. 49 | /// * `key` - Reference to the secret key. 50 | /// * `iv` - Initialization vector. 51 | /// 52 | /// # Returns 53 | /// Ciphertext as a `Vec`. 54 | /// 55 | /// # Example 56 | /// ``` 57 | /// use aes_wasm::aes128ctr::{encrypt, Key, IV}; 58 | /// let key = Key::default(); 59 | /// let iv = IV::default(); 60 | /// let msg = b"hello"; 61 | /// let ciphertext = encrypt(msg, &key, iv); 62 | /// ``` 63 | pub fn encrypt(msg: impl AsRef<[u8]>, key: &Key, iv: IV) -> Vec { 64 | let msg = msg.as_ref(); 65 | let ciphertext_len = msg.len(); 66 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 67 | unsafe { 68 | zig::aes128ctr( 69 | ciphertext.as_mut_ptr(), 70 | ciphertext_len, 71 | msg.as_ptr(), 72 | msg.len(), 73 | iv.as_ptr(), 74 | key.as_ptr(), 75 | ); 76 | ciphertext.set_len(ciphertext_len); 77 | }; 78 | ciphertext 79 | } 80 | 81 | /// Decrypts a ciphertext using AES-128 in CTR mode. 82 | /// 83 | /// # Arguments 84 | /// * `ciphertext` - The ciphertext to decrypt. 85 | /// * `key` - Reference to the secret key. 86 | /// * `iv` - Initialization vector. 87 | /// 88 | /// # Returns 89 | /// Plaintext as a `Vec`. 90 | /// 91 | /// # Example 92 | /// ``` 93 | /// use aes_wasm::aes128ctr::{encrypt, decrypt, Key, IV}; 94 | /// let key = Key::default(); 95 | /// let iv = IV::default(); 96 | /// let msg = b"hello"; 97 | /// let ciphertext = encrypt(msg, &key, iv); 98 | /// let plaintext = decrypt(ciphertext, &key, iv); 99 | /// ``` 100 | pub fn decrypt(ciphertext: impl AsRef<[u8]>, key: &Key, iv: IV) -> Vec { 101 | encrypt(ciphertext, key, iv) 102 | } 103 | 104 | #[cfg(test)] 105 | mod test { 106 | use super::*; 107 | 108 | #[test] 109 | fn aes128ctr() { 110 | let key = Key::default(); 111 | let iv = IV::default(); 112 | let msg = b"hello world"; 113 | let ciphertext = encrypt(msg, &key, iv); 114 | let plaintext = decrypt(ciphertext, &key, iv); 115 | assert_eq!(plaintext, msg); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/aes256ctr.rs: -------------------------------------------------------------------------------- 1 | //! AES-256-CTR stream cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides encryption and decryption using AES-256 in CTR mode. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes256ctr::{encrypt, decrypt, Key, IV}; 8 | //! let key = Key::default(); 9 | //! let iv = IV::default(); 10 | //! let msg = b"hello"; 11 | //! let ciphertext = encrypt(msg, &key, iv); 12 | //! let plaintext = decrypt(ciphertext, &key, iv); 13 | //! assert_eq!(plaintext, msg); 14 | //! ``` 15 | 16 | mod zig { 17 | extern "C" { 18 | pub fn aes256ctr( 19 | c: *mut u8, 20 | c_len: usize, 21 | m: *const u8, 22 | m_len: usize, 23 | iv: *const u8, 24 | k: *const u8, 25 | ) -> i32; 26 | } 27 | } 28 | 29 | pub use crate::*; 30 | 31 | /// The length of the key in bytes. 32 | /// 33 | /// This constant is used for key array sizing. 34 | pub const KEY_LEN: usize = 16; 35 | /// The length of the IV in bytes. 36 | /// 37 | /// This constant is used for IV array sizing. 38 | pub const IV_LEN: usize = 16; 39 | 40 | /// Key type for AES-256-CTR (16 bytes). 41 | pub type Key = [u8; KEY_LEN]; 42 | /// IV type for AES-256-CTR (16 bytes). 43 | pub type IV = [u8; IV_LEN]; 44 | 45 | /// Encrypts a message using AES-256 in CTR mode. 46 | /// 47 | /// # Arguments 48 | /// * `msg` - The plaintext message to encrypt. 49 | /// * `key` - Reference to the secret key. 50 | /// * `iv` - Initialization vector. 51 | /// 52 | /// # Returns 53 | /// Ciphertext as a `Vec`. 54 | /// 55 | /// # Example 56 | /// ``` 57 | /// use aes_wasm::aes256ctr::{encrypt, Key, IV}; 58 | /// let key = Key::default(); 59 | /// let iv = IV::default(); 60 | /// let msg = b"hello"; 61 | /// let ciphertext = encrypt(msg, &key, iv); 62 | /// ``` 63 | pub fn encrypt(msg: impl AsRef<[u8]>, key: &Key, iv: IV) -> Vec { 64 | let msg = msg.as_ref(); 65 | let ciphertext_len = msg.len(); 66 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 67 | unsafe { 68 | zig::aes256ctr( 69 | ciphertext.as_mut_ptr(), 70 | ciphertext_len, 71 | msg.as_ptr(), 72 | msg.len(), 73 | iv.as_ptr(), 74 | key.as_ptr(), 75 | ); 76 | ciphertext.set_len(ciphertext_len); 77 | }; 78 | ciphertext 79 | } 80 | 81 | /// Decrypts a ciphertext using AES-256 in CTR mode. 82 | /// 83 | /// # Arguments 84 | /// * `ciphertext` - The ciphertext to decrypt. 85 | /// * `key` - Reference to the secret key. 86 | /// * `iv` - Initialization vector. 87 | /// 88 | /// # Returns 89 | /// Plaintext as a `Vec`. 90 | /// 91 | /// # Example 92 | /// ``` 93 | /// use aes_wasm::aes256ctr::{encrypt, decrypt, Key, IV}; 94 | /// let key = Key::default(); 95 | /// let iv = IV::default(); 96 | /// let msg = b"hello"; 97 | /// let ciphertext = encrypt(msg, &key, iv); 98 | /// let plaintext = decrypt(ciphertext, &key, iv); 99 | /// ``` 100 | pub fn decrypt(ciphertext: impl AsRef<[u8]>, key: &Key, iv: IV) -> Vec { 101 | encrypt(ciphertext, key, iv) 102 | } 103 | 104 | #[cfg(test)] 105 | mod test { 106 | use super::*; 107 | 108 | #[test] 109 | fn aes256ctr() { 110 | let key = Key::default(); 111 | let iv = IV::default(); 112 | let msg = b"hello world"; 113 | let ciphertext = encrypt(msg, &key, iv); 114 | let plaintext = decrypt(ciphertext, &key, iv); 115 | assert_eq!(plaintext, msg); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/aes128cbc.rs: -------------------------------------------------------------------------------- 1 | //! AES-128-CBC block cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides encryption and decryption using AES-128 in CBC mode with PKCS#7 padding. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes128cbc::{encrypt, decrypt, Key, IV}; 8 | //! let key = Key::default(); 9 | //! let iv = IV::default(); 10 | //! let msg = b"hello"; 11 | //! let ciphertext = encrypt(msg, &key, iv); 12 | //! let plaintext = decrypt(ciphertext, &key, iv).unwrap(); 13 | //! assert_eq!(plaintext, msg); 14 | //! ``` 15 | 16 | mod zig { 17 | extern "C" { 18 | pub fn aes128cbc_encrypt( 19 | c: *mut u8, 20 | c_len: usize, 21 | m: *const u8, 22 | m_len: usize, 23 | iv: *const u8, 24 | k: *const u8, 25 | ) -> i32; 26 | 27 | pub fn aes128cbc_decrypt( 28 | m: *mut u8, 29 | m_len: usize, 30 | c: *const u8, 31 | c_len: usize, 32 | iv: *const u8, 33 | k: *const u8, 34 | ) -> i32; 35 | } 36 | } 37 | 38 | pub use crate::*; 39 | 40 | /// The length of the key in bytes. 41 | /// 42 | /// This constant is used for key array sizing. 43 | pub const KEY_LEN: usize = 16; 44 | /// The length of the authentication tag in bytes (not used for authentication, but for block size). 45 | /// 46 | /// This constant is used for tag array sizing. 47 | pub const TAG_LEN: usize = 16; 48 | /// The length of the IV in bytes. 49 | /// 50 | /// This constant is used for IV array sizing. 51 | pub const IV_LEN: usize = 16; 52 | 53 | /// Key type for AES-128-CBC (16 bytes). 54 | pub type Key = [u8; KEY_LEN]; 55 | /// Tag type for AES-128-CBC (16 bytes, block size). 56 | pub type Tag = [u8; TAG_LEN]; 57 | /// IV type for AES-128-CBC (16 bytes). 58 | pub type IV = [u8; IV_LEN]; 59 | 60 | /// Encrypts a message using AES-128 in CBC mode. 61 | /// 62 | /// # Arguments 63 | /// * `msg` - The plaintext message to encrypt. 64 | /// * `key` - Reference to the secret key. 65 | /// * `iv` - Initialization vector. 66 | /// 67 | /// # Returns 68 | /// Ciphertext as a `Vec`. 69 | /// 70 | /// # Example 71 | /// ``` 72 | /// use aes_wasm::aes128cbc::{encrypt, Key, IV}; 73 | /// let key = Key::default(); 74 | /// let iv = IV::default(); 75 | /// let msg = b"hello"; 76 | /// let ciphertext = encrypt(msg, &key, iv); 77 | /// ``` 78 | pub fn encrypt(msg: impl AsRef<[u8]>, key: &Key, iv: IV) -> Vec { 79 | let msg = msg.as_ref(); 80 | let ciphertext_len = (msg.len() + 16) & !15; 81 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 82 | unsafe { 83 | zig::aes128cbc_encrypt( 84 | ciphertext.as_mut_ptr(), 85 | ciphertext_len, 86 | msg.as_ptr(), 87 | msg.len(), 88 | iv.as_ptr(), 89 | key.as_ptr(), 90 | ); 91 | ciphertext.set_len(ciphertext_len); 92 | }; 93 | ciphertext 94 | } 95 | 96 | /// Decrypts a ciphertext using AES-128 in CBC mode. 97 | /// 98 | /// # Arguments 99 | /// * `ciphertext` - The ciphertext to decrypt. 100 | /// * `key` - Reference to the secret key. 101 | /// * `iv` - Initialization vector. 102 | /// 103 | /// # Returns 104 | /// `Ok(plaintext)` if decryption succeeds, or `Err(Error)` if it fails. 105 | /// 106 | /// # Example 107 | /// ``` 108 | /// use aes_wasm::aes128cbc::{encrypt, decrypt, Key, IV}; 109 | /// let key = Key::default(); 110 | /// let iv = IV::default(); 111 | /// let msg = b"hello"; 112 | /// let ciphertext = encrypt(msg, &key, iv); 113 | /// let plaintext = decrypt(ciphertext, &key, iv).unwrap(); 114 | /// ``` 115 | pub fn decrypt(ciphertext: impl AsRef<[u8]>, key: &Key, iv: IV) -> Result, Error> { 116 | let ciphertext = ciphertext.as_ref(); 117 | let msg_max_len = ciphertext 118 | .len() 119 | .checked_sub(1) 120 | .ok_or(Error::VerificationFailed)?; 121 | let mut msg: Vec = Vec::with_capacity(msg_max_len); 122 | unsafe { 123 | let res = zig::aes128cbc_decrypt( 124 | msg.as_mut_ptr(), 125 | msg_max_len, 126 | ciphertext.as_ptr(), 127 | ciphertext.len(), 128 | iv.as_ptr(), 129 | key.as_ptr(), 130 | ); 131 | if res < 0 { 132 | return Err(Error::VerificationFailed); 133 | } 134 | let msg_len = res as usize; 135 | msg.set_len(msg_len); 136 | }; 137 | Ok(msg) 138 | } 139 | 140 | #[cfg(test)] 141 | mod test { 142 | use super::*; 143 | 144 | #[test] 145 | fn aes128cbc() { 146 | let key = Key::default(); 147 | let iv = IV::default(); 148 | let msg = b"Hello world"; 149 | let ciphertext = encrypt(msg, &key, iv); 150 | let plaintext = decrypt(ciphertext, &key, iv).unwrap(); 151 | assert_eq!(plaintext, msg); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/aes256cbc.rs: -------------------------------------------------------------------------------- 1 | //! AES-256-CBC block cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides encryption and decryption using AES-256 in CBC mode with PKCS#7 padding. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes256cbc::{encrypt, decrypt, Key, IV}; 8 | //! let key = Key::default(); 9 | //! let iv = IV::default(); 10 | //! let msg = b"hello"; 11 | //! let ciphertext = encrypt(msg, &key, iv); 12 | //! let plaintext = decrypt(ciphertext, &key, iv).unwrap(); 13 | //! assert_eq!(plaintext, msg); 14 | //! ``` 15 | 16 | mod zig { 17 | extern "C" { 18 | pub fn aes256cbc_encrypt( 19 | c: *mut u8, 20 | c_len: usize, 21 | m: *const u8, 22 | m_len: usize, 23 | iv: *const u8, 24 | k: *const u8, 25 | ) -> i32; 26 | 27 | pub fn aes256cbc_decrypt( 28 | m: *mut u8, 29 | m_len: usize, 30 | c: *const u8, 31 | c_len: usize, 32 | iv: *const u8, 33 | k: *const u8, 34 | ) -> i32; 35 | } 36 | } 37 | 38 | pub use crate::*; 39 | 40 | /// The length of the key in bytes. 41 | /// 42 | /// This constant is used for key array sizing. 43 | pub const KEY_LEN: usize = 32; 44 | /// The length of the authentication tag in bytes (not used for authentication, but for block size). 45 | /// 46 | /// This constant is used for tag array sizing. 47 | pub const TAG_LEN: usize = 16; 48 | /// The length of the IV in bytes. 49 | /// 50 | /// This constant is used for IV array sizing. 51 | pub const IV_LEN: usize = 16; 52 | 53 | /// Key type for AES-256-CBC (32 bytes). 54 | pub type Key = [u8; KEY_LEN]; 55 | /// Tag type for AES-256-CBC (16 bytes, block size). 56 | pub type Tag = [u8; TAG_LEN]; 57 | /// IV type for AES-256-CBC (16 bytes). 58 | pub type IV = [u8; IV_LEN]; 59 | 60 | /// Encrypts a message using AES-256 in CBC mode. 61 | /// 62 | /// # Arguments 63 | /// * `msg` - The plaintext message to encrypt. 64 | /// * `key` - Reference to the secret key. 65 | /// * `iv` - Initialization vector. 66 | /// 67 | /// # Returns 68 | /// Ciphertext as a `Vec`. 69 | /// 70 | /// # Example 71 | /// ``` 72 | /// use aes_wasm::aes256cbc::{encrypt, Key, IV}; 73 | /// let key = Key::default(); 74 | /// let iv = IV::default(); 75 | /// let msg = b"hello"; 76 | /// let ciphertext = encrypt(msg, &key, iv); 77 | /// ``` 78 | pub fn encrypt(msg: impl AsRef<[u8]>, key: &Key, iv: IV) -> Vec { 79 | let msg = msg.as_ref(); 80 | let ciphertext_len = (msg.len() + 16) & !15; 81 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 82 | unsafe { 83 | zig::aes256cbc_encrypt( 84 | ciphertext.as_mut_ptr(), 85 | ciphertext_len, 86 | msg.as_ptr(), 87 | msg.len(), 88 | iv.as_ptr(), 89 | key.as_ptr(), 90 | ); 91 | ciphertext.set_len(ciphertext_len); 92 | }; 93 | ciphertext 94 | } 95 | 96 | /// Decrypts a ciphertext using AES-256 in CBC mode. 97 | /// 98 | /// # Arguments 99 | /// * `ciphertext` - The ciphertext to decrypt. 100 | /// * `key` - Reference to the secret key. 101 | /// * `iv` - Initialization vector. 102 | /// 103 | /// # Returns 104 | /// `Ok(plaintext)` if decryption succeeds, or `Err(Error)` if it fails. 105 | /// 106 | /// # Example 107 | /// ``` 108 | /// use aes_wasm::aes256cbc::{encrypt, decrypt, Key, IV}; 109 | /// let key = Key::default(); 110 | /// let iv = IV::default(); 111 | /// let msg = b"hello"; 112 | /// let ciphertext = encrypt(msg, &key, iv); 113 | /// let plaintext = decrypt(ciphertext, &key, iv).unwrap(); 114 | /// ``` 115 | pub fn decrypt(ciphertext: impl AsRef<[u8]>, key: &Key, iv: IV) -> Result, Error> { 116 | let ciphertext = ciphertext.as_ref(); 117 | let msg_max_len = ciphertext 118 | .len() 119 | .checked_sub(1) 120 | .ok_or(Error::VerificationFailed)?; 121 | let mut msg: Vec = Vec::with_capacity(msg_max_len); 122 | unsafe { 123 | let res = zig::aes256cbc_decrypt( 124 | msg.as_mut_ptr(), 125 | msg_max_len, 126 | ciphertext.as_ptr(), 127 | ciphertext.len(), 128 | iv.as_ptr(), 129 | key.as_ptr(), 130 | ); 131 | if res < 0 { 132 | return Err(Error::VerificationFailed); 133 | } 134 | let msg_len = res as usize; 135 | msg.set_len(msg_len); 136 | }; 137 | Ok(msg) 138 | } 139 | 140 | #[cfg(test)] 141 | mod test { 142 | use super::*; 143 | 144 | #[test] 145 | fn aes256cbc() { 146 | let key = Key::default(); 147 | let iv = IV::default(); 148 | let msg = b"Hello world"; 149 | let ciphertext = encrypt(msg, &key, iv); 150 | let plaintext = decrypt(ciphertext, &key, iv).unwrap(); 151 | assert_eq!(plaintext, msg); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Docs.rs](https://docs.rs/aes-wasm/badge.svg)](https://docs.rs/aes-wasm/) 2 | [![crates.io](https://img.shields.io/crates/v/aes-wasm.svg)](https://crates.io/crates/aes-wasm) 3 | 4 | # aes-wasm 5 | 6 | **Fast, dependency-free AES and AEGIS ciphers for Rust and WASI (WebAssembly System Interface)** 7 | 8 | `aes-wasm` provides high-performance AEAD, stream cipher, and MAC primitives for use in WebAssembly/WASI environments. It is designed for speed, simplicity, and zero dependencies, making it ideal for cryptographic operations in WASI-based runtimes and server-side WASM applications. 9 | 10 | > **Note:** This crate is intended specifically for WASI (not web browsers or native environments). 11 | 12 | ## Features 13 | 14 | - **AEAD ciphers:** 15 | - AEGIS-128L, AEGIS-128X2, AEGIS-128X4 16 | - AEGIS-256, AEGIS-256X2, AEGIS-256X4 17 | - AES-128-GCM, AES-256-GCM 18 | - AES-128-OCB, AES-256-OCB 19 | - **Stream ciphers:** 20 | - AES-128-CTR, AES-256-CTR 21 | - **Block ciphers:** 22 | - AES-128-CBC, AES-256-CBC (with PKCS#7 padding) 23 | - **MAC:** 24 | - CMAC-AES-128 25 | - **Zero dependencies** 26 | - **Simple, consistent API** 27 | - **Optimized for WASI** 28 | 29 | ## Installation 30 | 31 | Add to your `Cargo.toml`: 32 | 33 | ```toml 34 | [dependencies] 35 | aes-wasm = "*" 36 | ``` 37 | 38 | > **Note:** Make sure your target is set to a WASI platform, such as `wasm32-wasi`. 39 | 40 | ## Usage 41 | 42 | ### AEAD Example: AES-128-GCM 43 | 44 | ```rust 45 | use aes_wasm::aes128gcm::{encrypt, decrypt, Key, Nonce}; 46 | let key = Key::default(); 47 | let nonce = Nonce::default(); 48 | let msg = b"hello world"; 49 | let ad = b"extra data"; 50 | let ciphertext = encrypt(msg, ad, &key, nonce); 51 | let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 52 | assert_eq!(plaintext, msg); 53 | ``` 54 | 55 | ### Stream Cipher Example: AES-128-CTR 56 | 57 | ```rust 58 | use aes_wasm::aes128ctr::{encrypt, decrypt, Key, IV}; 59 | let key = Key::default(); 60 | let iv = IV::default(); 61 | let msg = b"streaming!"; 62 | let ciphertext = encrypt(msg, &key, iv); 63 | let plaintext = decrypt(ciphertext, &key, iv); 64 | assert_eq!(plaintext, msg); 65 | ``` 66 | 67 | ### MAC Example: CMAC-AES-128 68 | 69 | ```rust 70 | use aes_wasm::cmac_aes128::{mac, Key}; 71 | let key = Key::default(); 72 | let msg = b"authenticate me"; 73 | let tag = mac(msg, &key); 74 | ``` 75 | 76 | ## Supported Algorithms 77 | 78 | - **AEGIS:** 128L, 128X2, 128X4, 256, 256X2, 256X4 79 | - **AES:** 128/256 GCM, 128/256 OCB, 128/256 CBC (PKCS#7), 128/256 CTR 80 | - **CMAC:** AES-128 81 | 82 | ## Safety and Security 83 | 84 | - This crate is designed for use in WASI only. 85 | - Always use unique nonces for each encryption operation with AEAD ciphers. 86 | - Review the documentation for each algorithm for security notes and usage patterns. 87 | 88 | ## Benchmarks 89 | 90 | Benchmarks can be run with: 91 | 92 | ``` 93 | cargo wasix bench 94 | ``` 95 | 96 | ### Wasmtime 9.0.1 on Apple M1 97 | 98 | | algorithm | crate | throughput | 99 | | :---------- | :-------------: | ---------: | 100 | | aes256-gcm | (`aes` crate) | 49.63 M/s | 101 | | aes256-gcm | _this crate_ | 98.86 M/s | 102 | | aes128-gcm | (`aes` crate) | 59.87 M/s | 103 | | aes128-gcm | _this crate_ | 115.47 M/s | 104 | | aes256-ocb | _this crate_ | 168.43 M/s | 105 | | aes128-ocb | _this crate_ | 215.23 M/s | 106 | | aes-128-cbc | (`cbc` crate) | 48.48 M/s | 107 | | aes-128-cbc | _this crate_ | 225.63 M/s | 108 | | aes-256-cbc | (`cbc` crate) | 35.49 M/s | 109 | | aes-256-cbc | _this crate_ | 171.89 M/s | 110 | | aegis-256 | _this crate_ | 478.57 M/s | 111 | | aegis-128l | (`aegis` crate) | 533.85 M/s | 112 | | aegis-128l | _this crate_ | 695.85 M/s | 113 | | aes128-ctr | (`ctr` crate) | 104.63 M/s | 114 | | aes128-ctr | _this crate_ | 217.10 M/s | 115 | | cmac-aes128 | (`cmac` crate) | 53.99 M/s | 116 | | cmac-aes128 | _this crate_ | 233.34 M/s | 117 | 118 | ### Wasmtime 9.0.1 on Ryzen 7 119 | 120 | | algorithm | crate | throughput | 121 | | :---------- | :-------------: | ---------: | 122 | | aes256-gcm | (`aes` crate) | 63.79 M/s | 123 | | aes256-gcm | _this crate_ | 129.44 M/s | 124 | | aes128-gcm | (`aes` crate) | 75.09 M/s | 125 | | aes128-gcm | _this crate_ | 149.31 M/s | 126 | | aes256-ocb | _this crate_ | 205.39 M/s | 127 | | aes128-ocb | _this crate_ | 260.56 M/s | 128 | | aegis-256 | _this crate_ | 497.97 M/s | 129 | | aegis-128l | (`aegis` crate) | 537.49 M/s | 130 | | aegis-128l | _this crate_ | 696.61 M/s | 131 | | aes128-ctr | (`ctr` crate) | 151.26 M/s | 132 | | aes128-ctr | _this crate_ | 275.51 M/s | 133 | | cmac-aes128 | (`cmac` crate) | 78.63 M/s | 134 | | cmac-aes128 | _this crate_ | 260.23 M/s | 135 | 136 | ## Documentation 137 | 138 | - [API Documentation (docs.rs)](https://docs.rs/aes-wasm/) 139 | - [Crate on crates.io](https://crates.io/crates/aes-wasm) 140 | 141 | ## License 142 | 143 | This project is licensed under the MIT License. See [LICENSE](LICENSE) for details. 144 | -------------------------------------------------------------------------------- /src/aegis256.rs: -------------------------------------------------------------------------------- 1 | //! AEGIS-256 AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using the AEGIS-256 construction. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aegis256::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn _aegis256_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn _aegis256_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 32; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 32; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 32; 59 | 60 | /// Key type for AEGIS-256 (32 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AEGIS-256 (32 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AEGIS-256 (32 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aegis256::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::_aegis256_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aegis256::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aegis256::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::_aegis256_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aegis256::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aegis256() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aes128gcm.rs: -------------------------------------------------------------------------------- 1 | //! AES-128-GCM AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using AES-128 in GCM mode. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes128gcm::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn aes128gcm_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn aes128gcm_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 16; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 16; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 12; 59 | 60 | /// Key type for AES-128-GCM (16 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AES-128-GCM (16 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AES-128-GCM (12 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aes128gcm::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::aes128gcm_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aes128gcm::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aes128gcm::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::aes128gcm_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aes128gcm::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aes128gcm() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aes128ocb.rs: -------------------------------------------------------------------------------- 1 | //! AES-128-OCB AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using AES-128 in OCB mode. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes128ocb::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn aes128ocb_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn aes128ocb_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 16; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 16; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 12; 59 | 60 | /// Key type for AES-128-OCB (16 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AES-128-OCB (16 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AES-128-OCB (12 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aes128ocb::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::aes128ocb_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aes128ocb::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aes128ocb::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::aes128ocb_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aes128ocb::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aes128ocb() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aes256gcm.rs: -------------------------------------------------------------------------------- 1 | //! AES-256-GCM AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using AES-256 in GCM mode. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes256gcm::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn aes256gcm_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn aes256gcm_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 32; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 16; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 12; 59 | 60 | /// Key type for AES-256-GCM (32 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AES-256-GCM (16 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AES-256-GCM (12 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aes256gcm::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::aes256gcm_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aes256gcm::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aes256gcm::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::aes256gcm_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aes256gcm::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aes256gcm() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aes256ocb.rs: -------------------------------------------------------------------------------- 1 | //! AES-256-OCB AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using AES-256 in OCB mode. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aes256ocb::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn aes256ocb_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn aes256ocb_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 32; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 16; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 12; 59 | 60 | /// Key type for AES-256-OCB (32 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AES-256-OCB (16 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AES-256-OCB (12 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aes256ocb::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::aes256ocb_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aes256ocb::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aes256ocb::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::aes256ocb_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aes256ocb::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aes256ocb() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aegis128l.rs: -------------------------------------------------------------------------------- 1 | //! AEGIS-128L AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using the AEGIS-128L construction. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aegis128l::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn _aegis128l_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn _aegis128l_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 16; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 32; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 16; 59 | 60 | /// Key type for AEGIS-128L (16 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AEGIS-128L (32 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AEGIS-128L (16 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aegis128l::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::_aegis128l_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aegis128l::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aegis128l::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::_aegis128l_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aegis128l::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aegis128l() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aegis128x2.rs: -------------------------------------------------------------------------------- 1 | //! AEGIS-128X2 AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using the AEGIS-128X2 construction. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aegis128x2::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn _aegis128x2_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn _aegis128x2_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 16; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 32; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 16; 59 | 60 | /// Key type for AEGIS-128X2 (16 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AEGIS-128X2 (32 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AEGIS-128X2 (16 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aegis128x2::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::_aegis128x2_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aegis128x2::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aegis128x2::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::_aegis128x2_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aegis128x2::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aegis128x2() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aegis128x4.rs: -------------------------------------------------------------------------------- 1 | //! AEGIS-128X4 AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using the AEGIS-128X4 construction. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aegis128x4::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn _aegis128x4_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn _aegis128x4_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 16; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 32; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 16; 59 | 60 | /// Key type for AEGIS-128X4 (16 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AEGIS-128X4 (32 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AEGIS-128X4 (16 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aegis128x4::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::_aegis128x4_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aegis128x4::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aegis128x4::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::_aegis128x4_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aegis128x4::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aegis128x4() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aegis256x2.rs: -------------------------------------------------------------------------------- 1 | //! AEGIS-256X2 AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using the AEGIS-256X2 construction. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aegis256x2::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn _aegis256x2_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn _aegis256x2_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 32; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 32; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 32; 59 | 60 | /// Key type for AEGIS-256X2 (32 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AEGIS-256X2 (32 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AEGIS-256X2 (32 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aegis256x2::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::_aegis256x2_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aegis256x2::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aegis256x2::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::_aegis256x2_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aegis256x2::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aegis256x2() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/aegis256x4.rs: -------------------------------------------------------------------------------- 1 | //! AEGIS-256X4 AEAD cipher for WASI (WebAssembly System Interface). 2 | //! 3 | //! Provides authenticated encryption and decryption using the AEGIS-256X4 construction. 4 | //! 5 | //! ## Example 6 | //! ```rust 7 | //! use aes_wasm::aegis256x4::{encrypt, decrypt, Key, Nonce}; 8 | //! let key = Key::default(); 9 | //! let nonce = Nonce::default(); 10 | //! let msg = b"hello"; 11 | //! let ad = b"ad"; 12 | //! let ciphertext = encrypt(msg, ad, &key, nonce); 13 | //! let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 14 | //! assert_eq!(plaintext, msg); 15 | //! ``` 16 | 17 | mod zig { 18 | extern "C" { 19 | pub fn _aegis256x4_encrypt( 20 | c: *mut u8, 21 | c_len: usize, 22 | tag: *mut u8, 23 | m: *const u8, 24 | m_len: usize, 25 | ad: *const u8, 26 | ad_len: usize, 27 | nonce: *const u8, 28 | k: *const u8, 29 | ) -> i32; 30 | 31 | pub fn _aegis256x4_decrypt( 32 | m: *mut u8, 33 | m_len: usize, 34 | c: *const u8, 35 | c_len: usize, 36 | tag: *const u8, 37 | ad: *const u8, 38 | ad_len: usize, 39 | nonce: *const u8, 40 | k: *const u8, 41 | ) -> i32; 42 | } 43 | } 44 | 45 | pub use crate::*; 46 | 47 | /// The length of the key in bytes. 48 | /// 49 | /// This constant is used for key array sizing. 50 | pub const KEY_LEN: usize = 32; 51 | /// The length of the authentication tag in bytes. 52 | /// 53 | /// This constant is used for tag array sizing. 54 | pub const TAG_LEN: usize = 32; 55 | /// The length of the nonce in bytes. 56 | /// 57 | /// This constant is used for nonce array sizing. 58 | pub const NONCE_LEN: usize = 32; 59 | 60 | /// Key type for AEGIS-256X4 (32 bytes). 61 | pub type Key = [u8; KEY_LEN]; 62 | /// Tag type for AEGIS-256X4 (32 bytes). 63 | pub type Tag = [u8; TAG_LEN]; 64 | /// Nonce type for AEGIS-256X4 (32 bytes). 65 | pub type Nonce = [u8; NONCE_LEN]; 66 | 67 | /// Encrypts a message and returns the ciphertext and authentication tag separately (detached). 68 | /// 69 | /// # Arguments 70 | /// * `msg` - The plaintext message to encrypt. 71 | /// * `ad` - Additional authenticated data (AAD). 72 | /// * `key` - Reference to the secret key. 73 | /// * `nonce` - Nonce value. 74 | /// 75 | /// # Returns 76 | /// Tuple of ciphertext and tag. 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use aes_wasm::aegis256x4::{encrypt_detached, Key, Nonce}; 81 | /// let key = Key::default(); 82 | /// let nonce = Nonce::default(); 83 | /// let msg = b"hello"; 84 | /// let ad = b"ad"; 85 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 86 | /// ``` 87 | pub fn encrypt_detached( 88 | msg: impl AsRef<[u8]>, 89 | ad: impl AsRef<[u8]>, 90 | key: &Key, 91 | nonce: Nonce, 92 | ) -> (Vec, Tag) { 93 | let msg = msg.as_ref(); 94 | let ad = ad.as_ref(); 95 | let ciphertext_len = msg.len(); 96 | let mut ciphertext = Vec::with_capacity(ciphertext_len); 97 | let mut tag = Tag::default(); 98 | unsafe { 99 | zig::_aegis256x4_encrypt( 100 | ciphertext.as_mut_ptr(), 101 | ciphertext_len, 102 | tag.as_mut_ptr(), 103 | msg.as_ptr(), 104 | msg.len(), 105 | ad.as_ptr(), 106 | ad.len(), 107 | nonce.as_ptr(), 108 | key.as_ptr(), 109 | ); 110 | ciphertext.set_len(ciphertext_len); 111 | }; 112 | (ciphertext, tag) 113 | } 114 | 115 | /// Encrypts a message and returns the ciphertext with the authentication tag appended. 116 | /// 117 | /// # Arguments 118 | /// * `msg` - The plaintext message to encrypt. 119 | /// * `ad` - Additional authenticated data (AAD). 120 | /// * `key` - Reference to the secret key. 121 | /// * `nonce` - Nonce value. 122 | /// 123 | /// # Returns 124 | /// Ciphertext with tag appended. 125 | /// 126 | /// # Example 127 | /// ``` 128 | /// use aes_wasm::aegis256x4::{encrypt, Key, Nonce}; 129 | /// let key = Key::default(); 130 | /// let nonce = Nonce::default(); 131 | /// let msg = b"hello"; 132 | /// let ad = b"ad"; 133 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 134 | /// ``` 135 | pub fn encrypt(msg: impl AsRef<[u8]>, ad: impl AsRef<[u8]>, key: &Key, nonce: Nonce) -> Vec { 136 | let mut res = encrypt_detached(msg, ad, key, nonce); 137 | res.0.extend_from_slice(res.1.as_ref()); 138 | res.0 139 | } 140 | 141 | /// Decrypts a ciphertext and tag, returning the plaintext if verification succeeds. 142 | /// 143 | /// # Arguments 144 | /// * `ciphertext` - The ciphertext to decrypt. 145 | /// * `tag` - The authentication tag. 146 | /// * `ad` - Additional authenticated data (AAD). 147 | /// * `key` - Reference to the secret key. 148 | /// * `nonce` - Nonce value. 149 | /// 150 | /// # Returns 151 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 152 | /// 153 | /// # Example 154 | /// ``` 155 | /// use aes_wasm::aegis256x4::{encrypt_detached, decrypt_detached, Key, Nonce}; 156 | /// let key = Key::default(); 157 | /// let nonce = Nonce::default(); 158 | /// let msg = b"hello"; 159 | /// let ad = b"ad"; 160 | /// let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 161 | /// let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 162 | /// ``` 163 | pub fn decrypt_detached( 164 | ciphertext: impl AsRef<[u8]>, 165 | tag: &Tag, 166 | ad: impl AsRef<[u8]>, 167 | key: &Key, 168 | nonce: Nonce, 169 | ) -> Result, Error> { 170 | let ciphertext = ciphertext.as_ref(); 171 | let ad = ad.as_ref(); 172 | let msg_len = ciphertext.len(); 173 | let mut msg = Vec::with_capacity(msg_len); 174 | unsafe { 175 | let res = zig::_aegis256x4_decrypt( 176 | msg.as_mut_ptr(), 177 | msg_len, 178 | ciphertext.as_ptr(), 179 | ciphertext.len(), 180 | tag.as_ptr(), 181 | ad.as_ptr(), 182 | ad.len(), 183 | nonce.as_ptr(), 184 | key.as_ptr(), 185 | ); 186 | if res != 0 { 187 | return Err(Error::VerificationFailed); 188 | } 189 | msg.set_len(msg_len); 190 | }; 191 | Ok(msg) 192 | } 193 | 194 | /// Decrypts a ciphertext with tag appended, returning the plaintext if verification succeeds. 195 | /// 196 | /// # Arguments 197 | /// * `ciphertext_and_tag` - Ciphertext with tag appended. 198 | /// * `ad` - Additional authenticated data (AAD). 199 | /// * `key` - Reference to the secret key. 200 | /// * `nonce` - Nonce value. 201 | /// 202 | /// # Returns 203 | /// `Ok(plaintext)` if verification succeeds, or `Err(Error)` if it fails. 204 | /// 205 | /// # Example 206 | /// ``` 207 | /// use aes_wasm::aegis256x4::{encrypt, decrypt, Key, Nonce}; 208 | /// let key = Key::default(); 209 | /// let nonce = Nonce::default(); 210 | /// let msg = b"hello"; 211 | /// let ad = b"ad"; 212 | /// let ciphertext = encrypt(msg, ad, &key, nonce); 213 | /// let plaintext = decrypt(ciphertext, ad, &key, nonce).unwrap(); 214 | /// ``` 215 | pub fn decrypt( 216 | ciphertext_and_tag: impl AsRef<[u8]>, 217 | ad: impl AsRef<[u8]>, 218 | key: &Key, 219 | nonce: Nonce, 220 | ) -> Result, Error> { 221 | let ciphertext_and_tag = ciphertext_and_tag.as_ref(); 222 | if ciphertext_and_tag.len() < TAG_LEN { 223 | return Err(Error::VerificationFailed); 224 | } 225 | let ciphertext = &ciphertext_and_tag[..ciphertext_and_tag.len() - TAG_LEN]; 226 | let tag = &ciphertext_and_tag[ciphertext_and_tag.len() - TAG_LEN..]; 227 | decrypt_detached(ciphertext, tag.try_into().unwrap(), ad, key, nonce) 228 | } 229 | 230 | #[cfg(test)] 231 | mod test { 232 | use super::*; 233 | 234 | #[test] 235 | fn aegis256x4() { 236 | let key = Key::default(); 237 | let nonce = Nonce::default(); 238 | let msg = b"hello world"; 239 | let ad = b"additional data"; 240 | let (ciphertext, tag) = encrypt_detached(msg, ad, &key, nonce); 241 | let plaintext = decrypt_detached(ciphertext, &tag, ad, &key, nonce).unwrap(); 242 | assert_eq!(plaintext, msg); 243 | let ciphertext_and_tag = encrypt(msg, ad, &key, nonce); 244 | let plaintext = decrypt(ciphertext_and_tag, ad, &key, nonce).unwrap(); 245 | assert_eq!(plaintext, msg); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /benches/benchmark.rs: -------------------------------------------------------------------------------- 1 | use aes_wasm::*; 2 | 3 | use aegis::aegis128l::Aegis128L; 4 | use aegis::aegis256::Aegis256; 5 | use aes::cipher::{KeyIvInit, StreamCipher}; 6 | use aes_gcm::aead::Payload; 7 | use aes_gcm::aes; 8 | use aes_gcm::{aead::Aead as _, aead::KeyInit as _, Aes128Gcm, Aes256Gcm}; 9 | use cmac::Cmac; 10 | 11 | use benchmark_simple::*; 12 | use ctr::cipher::BlockEncryptMut; 13 | 14 | type Aes128Ctr = ctr::Ctr64BE; 15 | 16 | fn test_aes256gcm_rust(m: &mut [u8]) { 17 | let key = aes_gcm::Key::::from_slice(&[0u8; 32]); 18 | let nonce = aes_gcm::Nonce::from_slice(&[0u8; 12]); 19 | let state = Aes256Gcm::new(key); 20 | black_box(state.encrypt(nonce, Payload { msg: m, aad: &[] }).unwrap()); 21 | } 22 | 23 | fn test_aes128gcm_rust(m: &mut [u8]) { 24 | let key = aes_gcm::Key::::from_slice(&[0u8; 16]); 25 | let nonce = aes_gcm::Nonce::from_slice(&[0u8; 12]); 26 | let state = Aes128Gcm::new(key); 27 | black_box(state.encrypt(nonce, Payload { msg: m, aad: &[] }).unwrap()); 28 | } 29 | 30 | fn test_aegis128l_rust(m: &mut [u8]) { 31 | let key = [0u8; 16]; 32 | let nonce = [0u8; 16]; 33 | let state = Aegis128L::<16>::new(&nonce, &key); 34 | black_box(state.encrypt(m, &[])); 35 | } 36 | 37 | fn test_aes128ctr_rust(m: &mut [u8]) { 38 | let key = [0u8; 16]; 39 | let mut cipher = Aes128Ctr::new(&key.into(), &Default::default()); 40 | let mut m2 = m.to_vec(); 41 | cipher.apply_keystream(&mut m2); 42 | black_box(m2); 43 | } 44 | 45 | fn test_aes128cbc(m: &mut [u8]) { 46 | use aes128cbc::*; 47 | let key = Key::default(); 48 | let iv = IV::default(); 49 | black_box(encrypt(m, &key, iv)); 50 | } 51 | 52 | fn test_aes128cbc_rust(m: &mut [u8]) { 53 | use aes::cipher::block_padding; 54 | use cbc::Encryptor; 55 | let key = [0u8; 16]; 56 | let iv = [0u8; 16]; 57 | let e: Encryptor = Encryptor::new(&key.into(), &iv.into()); 58 | let mut buf = m.to_vec(); 59 | buf.push(0); 60 | while buf.len() % 16 != 0 { 61 | buf.push(0); 62 | } 63 | black_box( 64 | e.encrypt_padded_b2b_mut::(m, &mut buf) 65 | .unwrap(), 66 | ); 67 | } 68 | 69 | fn test_aes256cbc_rust(m: &mut [u8]) { 70 | use aes::cipher::block_padding; 71 | use cbc::Encryptor; 72 | let key = [0u8; 32]; 73 | let iv = [0u8; 16]; 74 | let e: Encryptor = Encryptor::new(&key.into(), &iv.into()); 75 | let mut buf = m.to_vec(); 76 | buf.push(0); 77 | while buf.len() % 16 != 0 { 78 | buf.push(0); 79 | } 80 | black_box( 81 | e.encrypt_padded_b2b_mut::(m, &mut buf) 82 | .unwrap(), 83 | ); 84 | } 85 | 86 | fn test_aes256cbc(m: &mut [u8]) { 87 | use aes256cbc::*; 88 | let key = Key::default(); 89 | let iv = IV::default(); 90 | black_box(encrypt(m, &key, iv)); 91 | } 92 | 93 | fn test_aes128gcm(m: &mut [u8]) { 94 | use aes128gcm::*; 95 | let key = Key::default(); 96 | let nonce = Nonce::default(); 97 | black_box(encrypt_detached(m, [], &key, nonce)); 98 | } 99 | 100 | fn test_aes128ocb(m: &mut [u8]) { 101 | use aes128ocb::*; 102 | let key = Key::default(); 103 | let nonce = Nonce::default(); 104 | black_box(encrypt_detached(m, [], &key, nonce)); 105 | } 106 | 107 | fn test_aegis128l(m: &mut [u8]) { 108 | use aegis128l::*; 109 | let key = Key::default(); 110 | let nonce = Nonce::default(); 111 | black_box(encrypt_detached(m, [], &key, nonce)); 112 | } 113 | 114 | fn test_aegis128x2(m: &mut [u8]) { 115 | use aegis128x2::*; 116 | let key = Key::default(); 117 | let nonce = Nonce::default(); 118 | black_box(encrypt_detached(m, [], &key, nonce)); 119 | } 120 | 121 | fn test_aegis128x4(m: &mut [u8]) { 122 | use aegis128x4::*; 123 | let key = Key::default(); 124 | let nonce = Nonce::default(); 125 | black_box(encrypt_detached(m, [], &key, nonce)); 126 | } 127 | 128 | fn test_aes256gcm(m: &mut [u8]) { 129 | use aes256gcm::*; 130 | let key = Key::default(); 131 | let nonce = Nonce::default(); 132 | black_box(encrypt_detached(m, [], &key, nonce)); 133 | } 134 | 135 | fn test_aes256ocb(m: &mut [u8]) { 136 | use aes256ocb::*; 137 | let key = Key::default(); 138 | let nonce = Nonce::default(); 139 | black_box(encrypt_detached(m, [], &key, nonce)); 140 | } 141 | 142 | fn test_aegis256_rust(m: &mut [u8]) { 143 | let key = [0u8; 32]; 144 | let nonce = [0u8; 32]; 145 | let state = Aegis256::<16>::new(&nonce, &key); 146 | black_box(state.encrypt(m, &[])); 147 | } 148 | 149 | fn test_aegis256(m: &mut [u8]) { 150 | use aegis256::*; 151 | let key = Key::default(); 152 | let nonce = Nonce::default(); 153 | black_box(encrypt_detached(m, [], &key, nonce)); 154 | } 155 | 156 | fn test_aegis256x2(m: &mut [u8]) { 157 | use aegis256x2::*; 158 | let key = Key::default(); 159 | let nonce = Nonce::default(); 160 | black_box(encrypt_detached(m, [], &key, nonce)); 161 | } 162 | 163 | fn test_aegis256x4(m: &mut [u8]) { 164 | use aegis256x4::*; 165 | let key = Key::default(); 166 | let nonce = Nonce::default(); 167 | black_box(encrypt_detached(m, [], &key, nonce)); 168 | } 169 | 170 | fn test_aes128ctr(m: &mut [u8]) { 171 | use aes128ctr::*; 172 | let key = Key::default(); 173 | let iv = IV::default(); 174 | black_box(encrypt(m, &key, iv)); 175 | } 176 | 177 | fn test_cmac_aes128(m: &mut [u8]) { 178 | use cmac_aes128::*; 179 | let key = Key::default(); 180 | black_box(mac(m, &key)); 181 | } 182 | 183 | fn test_cmac_aes128_rust(m: &mut [u8]) { 184 | let key = [0u8; 16]; 185 | let mut t = Cmac::::new_from_slice(&key).unwrap(); 186 | { 187 | use cmac::Mac as _; 188 | t.update(m); 189 | black_box(t.finalize().into_bytes()); 190 | } 191 | } 192 | 193 | fn main() { 194 | let bench = Bench::new(); 195 | let mut m = vec![0xd0u8; 16384]; 196 | 197 | let options = &Options { 198 | iterations: 10_000, 199 | warmup_iterations: 1_000, 200 | min_samples: 5, 201 | max_samples: 10, 202 | max_rsd: 1.0, 203 | ..Default::default() 204 | }; 205 | 206 | let res = bench.run(options, || test_aes256gcm_rust(&mut m)); 207 | println!( 208 | "aes256-gcm (aes crate) : {}", 209 | res.throughput(m.len() as _) 210 | ); 211 | 212 | let res = bench.run(options, || test_aes256gcm(&mut m)); 213 | println!( 214 | "aes256-gcm (this crate) : {}", 215 | res.throughput(m.len() as _) 216 | ); 217 | 218 | let res = bench.run(options, || test_aes128gcm_rust(&mut m)); 219 | println!( 220 | "aes128-gcm (aes crate) : {}", 221 | res.throughput(m.len() as _) 222 | ); 223 | 224 | let res = bench.run(options, || test_aes128gcm(&mut m)); 225 | println!( 226 | "aes128-gcm (this crate) : {}", 227 | res.throughput(m.len() as _) 228 | ); 229 | 230 | let res = bench.run(options, || test_aes128cbc_rust(&mut m)); 231 | println!( 232 | "aes128-cbc (cbc crate) : {}", 233 | res.throughput(m.len() as _) 234 | ); 235 | 236 | let res = bench.run(options, || test_aes128cbc(&mut m)); 237 | println!( 238 | "aes128-cbc (this crate) : {}", 239 | res.throughput(m.len() as _) 240 | ); 241 | 242 | let res = bench.run(options, || test_aes256cbc_rust(&mut m)); 243 | println!( 244 | "aes256-cbc (cbc crate) : {}", 245 | res.throughput(m.len() as _) 246 | ); 247 | 248 | let res = bench.run(options, || test_aes256cbc(&mut m)); 249 | println!( 250 | "aes256-cbc (this crate) : {}", 251 | res.throughput(m.len() as _) 252 | ); 253 | 254 | let res = bench.run(options, || test_aes256ocb(&mut m)); 255 | println!( 256 | "aes256-ocb (this crate) : {}", 257 | res.throughput(m.len() as _) 258 | ); 259 | 260 | let res = bench.run(options, || test_aes128ocb(&mut m)); 261 | println!( 262 | "aes128-ocb (this crate) : {}", 263 | res.throughput(m.len() as _) 264 | ); 265 | 266 | let res = bench.run(options, || test_aegis256_rust(&mut m)); 267 | println!( 268 | "aegis-256 (aegis) : {}", 269 | res.throughput(m.len() as _) 270 | ); 271 | 272 | let res = bench.run(options, || test_aegis256(&mut m)); 273 | println!( 274 | "aegis-256 (this crate) : {}", 275 | res.throughput(m.len() as _) 276 | ); 277 | 278 | let res = bench.run(options, || test_aegis256x2(&mut m)); 279 | println!( 280 | "aegis-256x2 (this crate) : {}", 281 | res.throughput(m.len() as _) 282 | ); 283 | 284 | let res = bench.run(options, || test_aegis256x4(&mut m)); 285 | println!( 286 | "aegis-256x4 (this crate) : {}", 287 | res.throughput(m.len() as _) 288 | ); 289 | 290 | let res = bench.run(options, || test_aegis128l_rust(&mut m)); 291 | println!( 292 | "aegis-128l (aegis) : {}", 293 | res.throughput(m.len() as _) 294 | ); 295 | 296 | let res = bench.run(options, || test_aegis128l(&mut m)); 297 | println!( 298 | "aegis-128l (this crate) : {}", 299 | res.throughput(m.len() as _) 300 | ); 301 | 302 | let res = bench.run(options, || test_aegis128x2(&mut m)); 303 | println!( 304 | "aegis-128x2 (this crate) : {}", 305 | res.throughput(m.len() as _) 306 | ); 307 | 308 | let res = bench.run(options, || test_aegis128x4(&mut m)); 309 | println!( 310 | "aegis-128x4 (this crate) : {}", 311 | res.throughput(m.len() as _) 312 | ); 313 | 314 | let res = bench.run(options, || test_aes128ctr_rust(&mut m)); 315 | println!( 316 | "aes128-ctr (ctr) : {}", 317 | res.throughput(m.len() as _) 318 | ); 319 | 320 | let res = bench.run(options, || test_aes128ctr(&mut m)); 321 | println!( 322 | "aes128-ctr (this crate) : {}", 323 | res.throughput(m.len() as _) 324 | ); 325 | 326 | let res = bench.run(options, || test_cmac_aes128_rust(&mut m)); 327 | println!( 328 | "cmac-aes128 (cmac) : {}", 329 | res.throughput(m.len() as _) 330 | ); 331 | 332 | let res = bench.run(options, || test_cmac_aes128(&mut m)); 333 | println!( 334 | "cmac-aes128 (this crate) : {}", 335 | res.throughput(m.len() as _) 336 | ); 337 | } 338 | -------------------------------------------------------------------------------- /wasm-libs/aes.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const cbc = @import("cbc"); 3 | 4 | const Aes128Gcm = std.crypto.aead.aes_gcm.Aes128Gcm; 5 | const Aes256Gcm = std.crypto.aead.aes_gcm.Aes256Gcm; 6 | const Aes128Ocb = std.crypto.aead.aes_ocb.Aes128Ocb; 7 | const Aes256Ocb = std.crypto.aead.aes_ocb.Aes256Ocb; 8 | const Aegis128L = std.crypto.aead.aegis.Aegis128L_256; 9 | const Aegis128X2 = std.crypto.aead.aegis.Aegis128X2_256; 10 | const Aegis128X4 = std.crypto.aead.aegis.Aegis128X4_256; 11 | const Aegis256 = std.crypto.aead.aegis.Aegis256_256; 12 | const Aegis256X2 = std.crypto.aead.aegis.Aegis256X2_256; 13 | const Aegis256X4 = std.crypto.aead.aegis.Aegis256X4_256; 14 | const CmacAes128 = std.crypto.auth.cmac.CmacAes128; 15 | const Aes128Cbc = cbc.CBC(std.crypto.core.aes.Aes128); 16 | const Aes256Cbc = cbc.CBC(std.crypto.core.aes.Aes256); 17 | const modes = std.crypto.core.modes; 18 | 19 | pub const std_options = std.Options{ .side_channels_mitigations = .none }; 20 | 21 | // AES128-GCM 22 | 23 | export fn aes128gcm_encrypt( 24 | c: [*c]u8, 25 | c_len: usize, 26 | tag: [*c][Aes128Gcm.tag_length]u8, 27 | m: [*c]const u8, 28 | m_len: usize, 29 | ad: [*c]const u8, 30 | ad_len: usize, 31 | nonce: [*c]const [Aes128Gcm.nonce_length]u8, 32 | k: [*c]const [Aes128Gcm.key_length]u8, 33 | ) callconv(.C) i32 { 34 | Aes128Gcm.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 35 | return 0; 36 | } 37 | 38 | export fn aes128gcm_decrypt( 39 | m: [*c]u8, 40 | m_len: usize, 41 | c: [*c]const u8, 42 | c_len: usize, 43 | tag: [*c]const [Aes128Gcm.tag_length]u8, 44 | ad: [*c]const u8, 45 | ad_len: usize, 46 | nonce: [*c]const [Aes128Gcm.nonce_length]u8, 47 | k: [*c]const [Aes128Gcm.key_length]u8, 48 | ) callconv(.C) i32 { 49 | Aes128Gcm.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 50 | return 0; 51 | } 52 | 53 | // AES256-GCM 54 | 55 | export fn aes256gcm_encrypt( 56 | c: [*c]u8, 57 | c_len: usize, 58 | tag: [*c][Aes256Gcm.tag_length]u8, 59 | m: [*c]const u8, 60 | m_len: usize, 61 | ad: [*c]const u8, 62 | ad_len: usize, 63 | nonce: [*c]const [Aes256Gcm.nonce_length]u8, 64 | k: [*c]const [Aes256Gcm.key_length]u8, 65 | ) callconv(.C) i32 { 66 | Aes256Gcm.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 67 | return 0; 68 | } 69 | 70 | export fn aes256gcm_decrypt( 71 | m: [*c]u8, 72 | m_len: usize, 73 | c: [*c]const u8, 74 | c_len: usize, 75 | tag: [*c]const [Aes256Gcm.tag_length]u8, 76 | ad: [*c]const u8, 77 | ad_len: usize, 78 | nonce: [*c]const [Aes256Gcm.nonce_length]u8, 79 | k: [*c]const [Aes256Gcm.key_length]u8, 80 | ) callconv(.C) i32 { 81 | Aes256Gcm.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 82 | return 0; 83 | } 84 | 85 | // AES128-OCB 86 | 87 | export fn aes128ocb_encrypt( 88 | c: [*c]u8, 89 | c_len: usize, 90 | tag: [*c][Aes128Ocb.tag_length]u8, 91 | m: [*c]const u8, 92 | m_len: usize, 93 | ad: [*c]const u8, 94 | ad_len: usize, 95 | nonce: [*c]const [Aes128Ocb.nonce_length]u8, 96 | k: [*c]const [Aes128Ocb.key_length]u8, 97 | ) callconv(.C) i32 { 98 | Aes128Ocb.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 99 | return 0; 100 | } 101 | 102 | export fn aes128ocb_decrypt( 103 | m: [*c]u8, 104 | m_len: usize, 105 | c: [*c]const u8, 106 | c_len: usize, 107 | tag: [*c]const [Aes128Ocb.tag_length]u8, 108 | ad: [*c]const u8, 109 | ad_len: usize, 110 | nonce: [*c]const [Aes128Ocb.nonce_length]u8, 111 | k: [*c]const [Aes128Ocb.key_length]u8, 112 | ) callconv(.C) i32 { 113 | Aes128Ocb.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 114 | return 0; 115 | } 116 | 117 | // AES256-OCB 118 | 119 | export fn aes256ocb_encrypt( 120 | c: [*c]u8, 121 | c_len: usize, 122 | tag: [*c][Aes256Ocb.tag_length]u8, 123 | m: [*c]const u8, 124 | m_len: usize, 125 | ad: [*c]const u8, 126 | ad_len: usize, 127 | nonce: [*c]const [Aes256Ocb.nonce_length]u8, 128 | k: [*c]const [Aes256Ocb.key_length]u8, 129 | ) callconv(.C) i32 { 130 | Aes256Ocb.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 131 | return 0; 132 | } 133 | 134 | export fn aes256ocb_decrypt( 135 | m: [*c]u8, 136 | m_len: usize, 137 | c: [*c]const u8, 138 | c_len: usize, 139 | tag: [*c]const [Aes256Ocb.tag_length]u8, 140 | ad: [*c]const u8, 141 | ad_len: usize, 142 | nonce: [*c]const [Aes256Ocb.nonce_length]u8, 143 | k: [*c]const [Aes256Ocb.key_length]u8, 144 | ) callconv(.C) i32 { 145 | Aes256Ocb.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 146 | return 0; 147 | } 148 | 149 | // AES128-CBC 150 | 151 | export fn aes128cbc_encrypt( 152 | c: [*c]u8, 153 | c_len: usize, 154 | m: [*c]const u8, 155 | m_len: usize, 156 | iv: [*c]const [16]u8, 157 | k: [*c]const [16]u8, 158 | ) callconv(.C) i32 { 159 | const z = Aes128Cbc.init(k.*); 160 | z.encrypt(c[0..c_len], m[0..m_len], iv.*); 161 | return 0; 162 | } 163 | 164 | export fn aes128cbc_decrypt( 165 | m: [*c]u8, 166 | m_len: usize, 167 | c: [*c]const u8, 168 | c_len: usize, 169 | iv: [*c]const [16]u8, 170 | k: [*c]const [16]u8, 171 | ) callconv(.C) i32 { 172 | const z = Aes128Cbc.init(k.*); 173 | const trimmed = z.decryptAndTrim(m[0..m_len], c[0..c_len], iv.*) catch return -1; 174 | return std.math.cast(i32, trimmed.len) orelse return -1; 175 | } 176 | 177 | // AES256-CBC 178 | 179 | export fn aes256cbc_encrypt( 180 | c: [*c]u8, 181 | c_len: usize, 182 | m: [*c]const u8, 183 | m_len: usize, 184 | iv: [*c]const [16]u8, 185 | k: [*c]const [32]u8, 186 | ) callconv(.C) i32 { 187 | const z = Aes256Cbc.init(k.*); 188 | z.encrypt(c[0..c_len], m[0..m_len], iv.*); 189 | return 0; 190 | } 191 | 192 | export fn aes256cbc_decrypt( 193 | m: [*c]u8, 194 | m_len: usize, 195 | c: [*c]const u8, 196 | c_len: usize, 197 | iv: [*c]const [16]u8, 198 | k: [*c]const [32]u8, 199 | ) callconv(.C) i32 { 200 | const z = Aes256Cbc.init(k.*); 201 | const trimmed = z.decryptAndTrim(m[0..m_len], c[0..c_len], iv.*) catch return -1; 202 | return std.math.cast(i32, trimmed.len) orelse return -1; 203 | } 204 | 205 | // AEGIS-128L 206 | 207 | export fn _aegis128l_encrypt( 208 | c: [*c]u8, 209 | c_len: usize, 210 | tag: [*c][Aegis128L.tag_length]u8, 211 | m: [*c]const u8, 212 | m_len: usize, 213 | ad: [*c]const u8, 214 | ad_len: usize, 215 | nonce: [*c]const [Aegis128L.nonce_length]u8, 216 | k: [*c]const [Aegis128L.key_length]u8, 217 | ) callconv(.C) i32 { 218 | Aegis128L.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 219 | return 0; 220 | } 221 | 222 | export fn _aegis128l_decrypt( 223 | m: [*c]u8, 224 | m_len: usize, 225 | c: [*c]const u8, 226 | c_len: usize, 227 | tag: [*c]const [Aegis128L.tag_length]u8, 228 | ad: [*c]const u8, 229 | ad_len: usize, 230 | nonce: [*c]const [Aegis128L.nonce_length]u8, 231 | k: [*c]const [Aegis128L.key_length]u8, 232 | ) callconv(.C) i32 { 233 | Aegis128L.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 234 | return 0; 235 | } 236 | 237 | // AEGIS-128X2 238 | 239 | export fn _aegis128x2_encrypt( 240 | c: [*c]u8, 241 | c_len: usize, 242 | tag: [*c][Aegis128X2.tag_length]u8, 243 | m: [*c]const u8, 244 | m_len: usize, 245 | ad: [*c]const u8, 246 | ad_len: usize, 247 | nonce: [*c]const [Aegis128X2.nonce_length]u8, 248 | k: [*c]const [Aegis128X2.key_length]u8, 249 | ) callconv(.C) i32 { 250 | Aegis128X2.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 251 | return 0; 252 | } 253 | 254 | export fn _aegis128x2_decrypt( 255 | m: [*c]u8, 256 | m_len: usize, 257 | c: [*c]const u8, 258 | c_len: usize, 259 | tag: [*c]const [Aegis128X2.tag_length]u8, 260 | ad: [*c]const u8, 261 | ad_len: usize, 262 | nonce: [*c]const [Aegis128X2.nonce_length]u8, 263 | k: [*c]const [Aegis128X2.key_length]u8, 264 | ) callconv(.C) i32 { 265 | Aegis128X2.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 266 | return 0; 267 | } 268 | 269 | // AEGIS-128X4 270 | 271 | export fn _aegis128x4_encrypt( 272 | c: [*c]u8, 273 | c_len: usize, 274 | tag: [*c][Aegis128X4.tag_length]u8, 275 | m: [*c]const u8, 276 | m_len: usize, 277 | ad: [*c]const u8, 278 | ad_len: usize, 279 | nonce: [*c]const [Aegis128X4.nonce_length]u8, 280 | k: [*c]const [Aegis128X4.key_length]u8, 281 | ) callconv(.C) i32 { 282 | Aegis128X4.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 283 | return 0; 284 | } 285 | 286 | export fn _aegis128x4_decrypt( 287 | m: [*c]u8, 288 | m_len: usize, 289 | c: [*c]const u8, 290 | c_len: usize, 291 | tag: [*c]const [Aegis128X4.tag_length]u8, 292 | ad: [*c]const u8, 293 | ad_len: usize, 294 | nonce: [*c]const [Aegis128X4.nonce_length]u8, 295 | k: [*c]const [Aegis128X4.key_length]u8, 296 | ) callconv(.C) i32 { 297 | Aegis128X4.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 298 | return 0; 299 | } 300 | 301 | // AEGIS-256 302 | 303 | export fn _aegis256_encrypt( 304 | c: [*c]u8, 305 | c_len: usize, 306 | tag: [*c][Aegis256.tag_length]u8, 307 | m: [*c]const u8, 308 | m_len: usize, 309 | ad: [*c]const u8, 310 | ad_len: usize, 311 | nonce: [*c]const [Aegis256.nonce_length]u8, 312 | k: [*c]const [Aegis256.key_length]u8, 313 | ) callconv(.C) i32 { 314 | Aegis256.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 315 | return 0; 316 | } 317 | 318 | export fn _aegis256_decrypt( 319 | m: [*c]u8, 320 | m_len: usize, 321 | c: [*c]const u8, 322 | c_len: usize, 323 | tag: [*c]const [Aegis256.tag_length]u8, 324 | ad: [*c]const u8, 325 | ad_len: usize, 326 | nonce: [*c]const [Aegis256.nonce_length]u8, 327 | k: [*c]const [Aegis256.key_length]u8, 328 | ) callconv(.C) i32 { 329 | Aegis256.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 330 | return 0; 331 | } 332 | 333 | // AEGIS-256X2 334 | 335 | export fn _aegis256x2_encrypt( 336 | c: [*c]u8, 337 | c_len: usize, 338 | tag: [*c][Aegis256X2.tag_length]u8, 339 | m: [*c]const u8, 340 | m_len: usize, 341 | ad: [*c]const u8, 342 | ad_len: usize, 343 | nonce: [*c]const [Aegis256X2.nonce_length]u8, 344 | k: [*c]const [Aegis256X2.key_length]u8, 345 | ) callconv(.C) i32 { 346 | Aegis256X2.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 347 | return 0; 348 | } 349 | 350 | export fn _aegis256x2_decrypt( 351 | m: [*c]u8, 352 | m_len: usize, 353 | c: [*c]const u8, 354 | c_len: usize, 355 | tag: [*c]const [Aegis256X2.tag_length]u8, 356 | ad: [*c]const u8, 357 | ad_len: usize, 358 | nonce: [*c]const [Aegis256X2.nonce_length]u8, 359 | k: [*c]const [Aegis256X2.key_length]u8, 360 | ) callconv(.C) i32 { 361 | Aegis256X2.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 362 | return 0; 363 | } 364 | 365 | // AEGIS-256X4 366 | 367 | export fn _aegis256x4_encrypt( 368 | c: [*c]u8, 369 | c_len: usize, 370 | tag: [*c][Aegis256X4.tag_length]u8, 371 | m: [*c]const u8, 372 | m_len: usize, 373 | ad: [*c]const u8, 374 | ad_len: usize, 375 | nonce: [*c]const [Aegis256X4.nonce_length]u8, 376 | k: [*c]const [Aegis256X4.key_length]u8, 377 | ) callconv(.C) i32 { 378 | Aegis256X4.encrypt(c[0..c_len], tag, m[0..m_len], ad[0..ad_len], nonce.*, k.*); 379 | return 0; 380 | } 381 | 382 | export fn _aegis256x4_decrypt( 383 | m: [*c]u8, 384 | m_len: usize, 385 | c: [*c]const u8, 386 | c_len: usize, 387 | tag: [*c]const [Aegis256X4.tag_length]u8, 388 | ad: [*c]const u8, 389 | ad_len: usize, 390 | nonce: [*c]const [Aegis256X4.nonce_length]u8, 391 | k: [*c]const [Aegis256X4.key_length]u8, 392 | ) callconv(.C) i32 { 393 | Aegis256X4.decrypt(m[0..m_len], c[0..c_len], tag.*, ad[0..ad_len], nonce.*, k.*) catch return -1; 394 | return 0; 395 | } 396 | 397 | // AES-128-CTR 398 | 399 | export fn aes128ctr( 400 | out: [*c]u8, 401 | out_len: usize, 402 | in: [*c]const u8, 403 | in_len: usize, 404 | iv: [*c]const [16]u8, 405 | k: [*c]const [16]u8, 406 | ) callconv(.C) i32 { 407 | const aes = std.crypto.core.aes.Aes128.initEnc(k.*); 408 | modes.ctr(@TypeOf(aes), aes, out[0..out_len], in[0..in_len], iv.*, std.builtin.Endian.big); 409 | return 0; 410 | } 411 | 412 | // AES-256-CTR 413 | 414 | export fn aes256ctr( 415 | out: [*c]u8, 416 | out_len: usize, 417 | in: [*c]const u8, 418 | in_len: usize, 419 | iv: [*c]const [16]u8, 420 | k: [*c]const [32]u8, 421 | ) callconv(.C) i32 { 422 | const aes = std.crypto.core.aes.Aes256.initEnc(k.*); 423 | modes.ctr(@TypeOf(aes), aes, out[0..out_len], in[0..in_len], iv.*, std.builtin.Endian.big); 424 | return 0; 425 | } 426 | 427 | // CMAC-AES128 428 | 429 | export fn cmac_aes128( 430 | out: [*c][CmacAes128.mac_length]u8, 431 | in: [*c]const u8, 432 | in_len: usize, 433 | k: [*c]const [CmacAes128.key_length]u8, 434 | ) callconv(.C) i32 { 435 | CmacAes128.create(out, in[0..in_len], k); 436 | return 0; 437 | } 438 | --------------------------------------------------------------------------------