ecb-0.1.1/.cargo_vcs_info.json0000644000000001360000000000100115640ustar { "git": { "sha1": "05332dea42d9f966788349d6856d9606d0644c9a" }, "path_in_vcs": "" }ecb-0.1.1/.github/workflows/publiish.yml000064400000000000000000000016650072674642500163530ustar 00000000000000name: Publish on: create: tags: - "v*" env: CARGO_INCREMENTAL: 0 CARGO_PROFILE_RELEASE_LTO: "fat" jobs: build: if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install Rust uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true components: rustfmt, clippy - run: cargo check --color always --all --all-targets - run: cargo fmt --check --all - run: cargo clippy --color always --all --all-targets - run: cargo test --color always --all --all-targets - name: publish crates run: cargo publish --token ${CRATES_TOKEN} env: CRATES_TOKEN: ${{ secrets.CRATES_TOKEN }} ecb-0.1.1/.github/workflows/test.yml000064400000000000000000000016650072674642500155130ustar 00000000000000name: Test on: [push, pull_request] env: CARGO_INCREMENTAL: 0 RUST_LOG: "debug" DIFF: 0 RUST_MIN_STACK: 4194304 jobs: ci: runs-on: ubuntu-latest strategy: matrix: rust: - stable - beta - nightly - "1.56" steps: - uses: actions/checkout@v3 - name: Install Rust uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true components: rustfmt, clippy - run: cargo check --color always --all --all-targets - if: matrix.rust != '1.56' run: cargo fmt --check --all - run: cargo clippy --color always --all --all-targets - run: cargo test --color always --all --all-targets ecb-0.1.1/.gitignore000064400000000000000000000000230072674642500123670ustar 00000000000000/target Cargo.lock ecb-0.1.1/Cargo.toml0000644000000025350000000000100075670ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "ecb" version = "0.1.1" authors = [ "RustCrypto Developers", "magic-akari", ] description = "Electronic Codebook (ECB) block cipher mode of operation" documentation = "https://docs.rs/ecb" readme = "README.md" keywords = [ "crypto", "block-mode", "ciphers", ] categories = [ "cryptography", "no-std", ] license = "MIT" repository = "https://github.com/magic-akari/ecb" resolver = "2" [package.metadata.docs.rs] all-features = true rustdoc-args = [ "--cfg", "docsrs", ] [dependencies.cipher] version = "0.4.3" [dev-dependencies.aes] version = "0.8.1" [dev-dependencies.cipher] version = "0.4.3" features = ["dev"] [dev-dependencies.hex-literal] version = "0.3.4" [features] alloc = ["cipher/alloc"] block-padding = ["cipher/block-padding"] default = ["block-padding"] std = [ "cipher/std", "alloc", ] ecb-0.1.1/Cargo.toml.orig000064400000000000000000000014100072674642500132670ustar 00000000000000[package] name = "ecb" version = "0.1.1" description = "Electronic Codebook (ECB) block cipher mode of operation" authors = ["RustCrypto Developers", "magic-akari"] license = "MIT" edition = "2021" rust-version = "1.56" readme = "README.md" documentation = "https://docs.rs/ecb" repository = "https://github.com/magic-akari/ecb" keywords = ["crypto", "block-mode", "ciphers"] categories = ["cryptography", "no-std"] [dependencies] cipher = "0.4.3" [dev-dependencies] aes = "0.8.1" cipher = { version = "0.4.3", features = ["dev"] } hex-literal = "0.3.4" [features] default = ["block-padding"] alloc = ["cipher/alloc"] std = ["cipher/std", "alloc"] block-padding = ["cipher/block-padding"] [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] ecb-0.1.1/LICENSE000064400000000000000000000020460072674642500114130ustar 00000000000000MIT License Copyright (c) magic-akari Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.ecb-0.1.1/README.md000064400000000000000000000031410072674642500116620ustar 00000000000000# RustCrypto: ECB [![crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] ![MIT licensed][license-image] ![Rust Version][rustc-image] [![Build Status][build-image]][build-link] Generic implementation of the [Electronic Codebook][ECB] (ECB) block cipher mode of operation. See [documentation][cipher-doc] of the `cipher` crate for additional information. ## Minimum Supported Rust Version Rust **1.56** or higher. Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump. ## SemVer Policy - All on-by-default features of this library are covered by SemVer - MSRV is considered exempt from SemVer as noted above ## License * [MIT license](http://opensource.org/licenses/MIT) [//]: # (badges) [crate-image]: https://img.shields.io/crates/v/ECB.svg [crate-link]: https://crates.io/crates/ECB [docs-image]: https://docs.rs/ecb/badge.svg [docs-link]: https://docs.rs/ecb/ [license-image]: https://img.shields.io/badge/license-MIT-blue.svg [rustc-image]: https://img.shields.io/badge/rustc-1.56+-blue.svg [build-image]: https://github.com/magic-akari/ecb/actions/workflows/test.yml/badge.svg?event=push [build-link]: https://github.com/magic-akari/ecb/actions/workflows/test.yml [//]: # (general links) [ECB]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#ECB [cipher-doc]: https://docs.rs/cipher/ ecb-0.1.1/src/decrypt.rs000064400000000000000000000060070072674642500132160ustar 00000000000000use cipher::{ crypto_common::{InnerInit, InnerUser}, generic_array::ArrayLength, inout::InOut, AlgorithmName, Block, BlockBackend, BlockCipher, BlockClosure, BlockDecryptMut, BlockSizeUser, ParBlocks, ParBlocksSizeUser, }; use core::fmt; /// ECB mode decryptor. #[derive(Clone)] pub struct Decryptor where C: BlockDecryptMut + BlockCipher, { cipher: C, } impl BlockSizeUser for Decryptor where C: BlockDecryptMut + BlockCipher, { type BlockSize = C::BlockSize; } impl BlockDecryptMut for Decryptor where C: BlockDecryptMut + BlockCipher, { fn decrypt_with_backend_mut(&mut self, f: impl BlockClosure) { let Self { cipher } = self; cipher.decrypt_with_backend_mut(Closure { f }) } } impl InnerUser for Decryptor where C: BlockDecryptMut + BlockCipher, { type Inner = C; } impl InnerInit for Decryptor where C: BlockDecryptMut + BlockCipher, { #[inline] fn inner_init(cipher: C) -> Self { Self { cipher } } } impl AlgorithmName for Decryptor where C: BlockDecryptMut + BlockCipher + AlgorithmName, { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("ecb::Decryptor<")?; ::write_alg_name(f)?; f.write_str(">") } } impl fmt::Debug for Decryptor where C: BlockDecryptMut + BlockCipher + AlgorithmName, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("ecb::Decryptor<")?; ::write_alg_name(f)?; f.write_str("> { ... }") } } struct Closure where BS: ArrayLength, BC: BlockClosure, { f: BC, } impl BlockSizeUser for Closure where BS: ArrayLength, BC: BlockClosure, { type BlockSize = BS; } impl BlockClosure for Closure where BS: ArrayLength, BC: BlockClosure, { #[inline(always)] fn call>(self, backend: &mut B) { let Self { f } = self; f.call(&mut Backend { backend }); } } struct Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { backend: &'a mut BK, } impl<'a, BS, BK> BlockSizeUser for Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { type BlockSize = BS; } impl<'a, BS, BK> ParBlocksSizeUser for Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { type ParBlocksSize = BK::ParBlocksSize; } impl<'a, BS, BK> BlockBackend for Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { #[inline(always)] fn proc_block(&mut self, block: InOut<'_, '_, Block>) { self.backend.proc_block(block); } #[inline(always)] fn proc_par_blocks(&mut self, blocks: InOut<'_, '_, ParBlocks>) { self.backend.proc_par_blocks(blocks); } } ecb-0.1.1/src/encrypt.rs000064400000000000000000000055560072674642500132400ustar 00000000000000use cipher::{ consts::U1, crypto_common::{InnerInit, InnerUser}, generic_array::ArrayLength, inout::InOut, AlgorithmName, Block, BlockBackend, BlockCipher, BlockClosure, BlockEncryptMut, BlockSizeUser, ParBlocksSizeUser, }; use core::fmt; /// ECB mode encryptor. #[derive(Clone)] pub struct Encryptor where C: BlockEncryptMut + BlockCipher, { cipher: C, } impl BlockSizeUser for Encryptor where C: BlockEncryptMut + BlockCipher, { type BlockSize = C::BlockSize; } impl BlockEncryptMut for Encryptor where C: BlockEncryptMut + BlockCipher, { fn encrypt_with_backend_mut(&mut self, f: impl BlockClosure) { let Self { cipher, .. } = self; cipher.encrypt_with_backend_mut(Closure { f }) } } impl InnerUser for Encryptor where C: BlockEncryptMut + BlockCipher, { type Inner = C; } impl InnerInit for Encryptor where C: BlockEncryptMut + BlockCipher, { #[inline] fn inner_init(cipher: C) -> Self { Self { cipher } } } impl AlgorithmName for Encryptor where C: BlockEncryptMut + BlockCipher + AlgorithmName, { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("ecb::Encryptor<")?; ::write_alg_name(f)?; f.write_str(">") } } impl fmt::Debug for Encryptor where C: BlockEncryptMut + BlockCipher + AlgorithmName, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("ecb::Encryptor<")?; ::write_alg_name(f)?; f.write_str("> { ... }") } } struct Closure where BS: ArrayLength, BC: BlockClosure, { f: BC, } impl BlockSizeUser for Closure where BS: ArrayLength, BC: BlockClosure, { type BlockSize = BS; } impl BlockClosure for Closure where BS: ArrayLength, BC: BlockClosure, { #[inline(always)] fn call>(self, backend: &mut B) { let Self { f, .. } = self; f.call(&mut Backend { backend }); } } struct Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { backend: &'a mut BK, } impl<'a, BS, BK> BlockSizeUser for Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { type BlockSize = BS; } impl<'a, BS, BK> ParBlocksSizeUser for Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { type ParBlocksSize = U1; } impl<'a, BS, BK> BlockBackend for Backend<'a, BS, BK> where BS: ArrayLength, BK: BlockBackend, { #[inline(always)] fn proc_block(&mut self, block: InOut<'_, '_, Block>) { self.backend.proc_block(block); } } ecb-0.1.1/src/lib.rs000064400000000000000000000070040072674642500123100ustar 00000000000000//! [Electronic Codebook][1] (ECB) mode. //! //! //! //! //! Mode functionality is accessed using traits from re-exported [`cipher`] crate. //! //! # ⚠️ Security Warning: Hazmat! //! //! This crate does not ensure ciphertexts are authentic! Thus ciphertext integrity //! is not verified, which can lead to serious vulnerabilities! //! //! # Example //! ``` //! # #[cfg(feature = "block-padding")] { //! use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit}; //! use hex_literal::hex; //! //! type Aes128EcbEnc = ecb::Encryptor; //! type Aes128EcbDec = ecb::Decryptor; //! //! let key = [0x42; 16]; //! let plaintext = *b"hello world! this is my plaintext."; //! let ciphertext = hex!( //! "42b153410851a931eb3e6c048867ae5f" //! "95eb20b42e176b07840db75688be9c70" //! "e4670ea0d87a71be5f9f3099b4fff3dc" //! ); //! //! // encrypt/decrypt in-place //! // buffer must be big enough for padded plaintext //! let mut buf = [0u8; 48]; //! let pt_len = plaintext.len(); //! buf[..pt_len].copy_from_slice(&plaintext); //! let ct = Aes128EcbEnc::new(&key.into()) //! .encrypt_padded_mut::(&mut buf, pt_len) //! .unwrap(); //! assert_eq!(ct, &ciphertext[..]); //! //! let pt = Aes128EcbDec::new(&key.into()) //! .decrypt_padded_mut::(&mut buf) //! .unwrap(); //! assert_eq!(pt, &plaintext); //! //! // encrypt/decrypt from buffer to buffer //! let mut buf = [0u8; 48]; //! let ct = Aes128EcbEnc::new(&key.into()) //! .encrypt_padded_b2b_mut::(&plaintext, &mut buf) //! .unwrap(); //! assert_eq!(ct, &ciphertext[..]); //! //! let mut buf = [0u8; 48]; //! let pt = Aes128EcbDec::new(&key.into()) //! .decrypt_padded_b2b_mut::(&ct, &mut buf) //! .unwrap(); //! assert_eq!(pt, &plaintext); //! # } //! ``` //! //! With enabled `alloc` (or `std`) feature you also can use allocating //! convinience methods: //! ``` //! # #[cfg(all(feature = "alloc", feature = "block-padding"))] { //! # use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyInit}; //! # use hex_literal::hex; //! # type Aes128EcbEnc = ecb::Encryptor; //! # type Aes128EcbDec = ecb::Decryptor; //! # let key = [0x42; 16]; //! # let plaintext = *b"hello world! this is my plaintext."; //! # let ciphertext = hex!( //! # "42b153410851a931eb3e6c048867ae5f" //! # "95eb20b42e176b07840db75688be9c70" //! # "e4670ea0d87a71be5f9f3099b4fff3dc" //! # ); //! let res = Aes128EcbEnc::new(&key.into()) //! .encrypt_padded_vec_mut::(&plaintext); //! assert_eq!(res[..], ciphertext[..]); //! let res = Aes128EcbDec::new(&key.into()) //! .decrypt_padded_vec_mut::(&res) //! .unwrap(); //! assert_eq!(res[..], plaintext[..]); //! # } //! ``` //! //! [1]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#ECB #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg", html_root_url = "https://docs.rs/ECB/0.1.2" )] #![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(missing_docs, rust_2018_idioms)] mod decrypt; mod encrypt; pub use cipher; pub use decrypt::Decryptor; pub use encrypt::Encryptor; ecb-0.1.1/tests/aes.rs000064400000000000000000000017460072674642500126740ustar 00000000000000#[cfg(test)] mod tests { #[test] fn ecb_aes128() { use aes::cipher::{block_padding::NoPadding, BlockDecryptMut, BlockEncryptMut, KeyInit}; use ecb::{Decryptor, Encryptor}; let key = include_bytes!("data/aes128.key.bin"); let plaintext = include_bytes!("data/aes128.plaintext.bin"); let ciphertext = include_bytes!("data/ecb-aes128.ciphertext.bin"); type Aes128EcbEnc = Encryptor; type Aes128EcbDec = Decryptor; let mut buf = *plaintext; let pt_len = buf.len(); let mode = Aes128EcbEnc::new(key.into()); assert_eq!( mode.encrypt_padded_mut::(&mut buf, pt_len) .unwrap(), &ciphertext[..] ); let mut buf = *ciphertext; let mode = Aes128EcbDec::new(key.into()); assert_eq!( mode.decrypt_padded_mut::(&mut buf).unwrap(), &plaintext[..] ); } } ecb-0.1.1/tests/data/aes128.key.bin000064400000000000000000000000200072674642500147330ustar 00000000000000+~(Ҧ O<ecb-0.1.1/tests/data/aes128.plaintext.bin000064400000000000000000000004400072674642500161610ustar 00000000000000]?,7}#S_S^R*9Z6վb'aPѺ6y٩`ʑ|}uI+fI|L_<gqz\{sh oi4P]ER>a+~09O@lط 2oXM[%F1̫bc־>ϗ+)RSqi(Ţ9FO܀UNwU@О!8Ptbzl;VE&{04R!{%e批Vg &w+xkB2#ݥt]C6%+/Բn #hT*{z$ϢI nb؟`MUVBs06 #?('~/:07"