diff --git a/.gitignore b/.gitignore index 471f9bc..f1784ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target /.idea/ -rfish.iml \ No newline at end of file +rfish.iml +rfish.h +main diff --git a/Cargo.lock b/Cargo.lock index 48d9841..82bfd94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,54 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "cbindgen" +version = "0.24.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b922faaf31122819ec80c4047cc684c6979a087366c069611e33649bf98e18d" +dependencies = [ + "clap", + "heck", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 1.0.109", + "tempfile", + "toml", +] + [[package]] name = "cc" version = "1.0.82" @@ -23,6 +65,57 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_lex", + "indexmap", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "errno" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "foreign-types" version = "0.3.2" @@ -39,10 +132,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] -name = "libc" -version = "0.2.144" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "linux-raw-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "once_cell" @@ -56,7 +198,7 @@ version = "0.10.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -73,7 +215,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.28", ] [[package]] @@ -88,6 +230,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" + [[package]] name = "pkg-config" version = "0.3.27" @@ -112,13 +260,90 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "rfish" version = "0.1.0" dependencies = [ + "cbindgen", "openssl", ] +[[package]] +name = "rustix" +version = "0.38.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "serde" +version = "1.0.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "serde_json" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.28" @@ -130,6 +355,43 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "unicode-ident" version = "1.0.11" @@ -141,3 +403,100 @@ name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/Cargo.toml b/Cargo.toml index 9235f40..8989f6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib"] + [dependencies] openssl = "0.10.56" + +[build-dependencies] +cbindgen = "0.24.0" \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..36e8a73 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +# Makefile + +RUST_LIB_DIR = target/debug/ +RUST_LIB_NAME = rfish + +.PHONY: all clean + +all: cargo_build main + +cargo_build: + cargo build + +main: rfish.c + gcc -o main rfish.c -L$(RUST_LIB_DIR) -Wl,-rpath=$(RUST_LIB_DIR) -l$(RUST_LIB_NAME) -ldl + +clean: + rm -f main \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..dd19f84 --- /dev/null +++ b/build.rs @@ -0,0 +1,14 @@ +extern crate cbindgen; + +use std::env; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + + cbindgen::Builder::new() + .with_crate(crate_dir) + .with_language(cbindgen::Language::C) + .generate() + .expect("Unable to generate bindings") + .write_to_file("rfish.h"); +} \ No newline at end of file diff --git a/rfish.c b/rfish.c new file mode 100644 index 0000000..ab89b06 --- /dev/null +++ b/rfish.c @@ -0,0 +1,20 @@ +#include +#include "rfish.h" + +int main() { + const uint8_t key[] = "chaveULTRAgulosa"; + uintptr_t key_len = sizeof(key) - 1; + + const uint8_t input[] = "teste123"; + uintptr_t input_len = sizeof(input) - 1; + + char *encrypted = encrypt_cbc(key, key_len, input, input_len); + if (encrypted) { + printf("Encrypted: %s\n", encrypted); + free(encrypted); + } else { + printf("Encryption failed.\n"); + } + + return 0; +} \ No newline at end of file diff --git a/src/main.rs b/src/lib.rs similarity index 63% rename from src/main.rs rename to src/lib.rs index ae6d332..0151757 100644 --- a/src/main.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +use std::ffi::CString; +use std::os::raw::c_char; use openssl::cipher::Cipher; use openssl::cipher_ctx::CipherCtx; @@ -68,13 +70,43 @@ impl Base64 { } } +enum Mode { + ECB, + CBC, +} + +#[no_mangle] +pub extern "C" fn encrypt_cbc(key: *const u8, key_len: usize, input: *const u8, input_len: usize) -> *mut c_char { + let key_slice = unsafe { std::slice::from_raw_parts(key, key_len) }; + let input_slice = unsafe { std::slice::from_raw_parts(input, input_len) }; + + let fish = Fish::new(key_slice, Mode::ECB); + let result = fish.encrypt(input_slice); + + let result_str = CString::new(result).unwrap(); + result_str.into_raw() +} + +#[no_mangle] +pub extern "C" fn decrypt_cbc(key: *const u8, key_len: usize, input: *const u8, input_len: usize) -> *mut c_char { + let key_slice = unsafe { std::slice::from_raw_parts(key, key_len) }; + let input_slice = unsafe { std::slice::from_raw_parts(input, input_len) }; + + let fish = Fish::new(key_slice, Mode::ECB); + let result = fish.decrypt(input_slice); + + let result_str = CString::new(result).unwrap(); + result_str.into_raw() +} + struct Fish { key: Vec, + mode: Mode, } impl Fish { - pub fn new(key: &[u8]) -> Fish { - Fish { key: key.to_vec() } + pub fn new(key: &[u8], mode: Mode) -> Fish { + Fish { key: key.to_vec(), mode } } fn get_padded_input(&self, input: &[u8]) -> Vec { @@ -90,6 +122,20 @@ impl Fish { } pub fn encrypt(&self, input: &[u8]) -> String { + match self.mode { + Mode::ECB => self.encrypt_ecb(input), + Mode::CBC => panic!("CBC not implemented yet") + } + } + + pub fn decrypt(&self, input: &[u8]) -> String { + match self.mode { + Mode::ECB => self.decrypt_ecb(input), + Mode::CBC => panic!("CBC not implemented yet") + } + } + + fn encrypt_ecb(&self, input: &[u8]) -> String { let cipher = Cipher::bf_ecb(); let mut ctx = CipherCtx::new().unwrap(); ctx.encrypt_init(Some(cipher), Some(&self.key), None).unwrap(); @@ -99,16 +145,18 @@ impl Fish { let padded_input = self.get_padded_input(input); ctx.cipher_update_vec(&padded_input, &mut ciphertext).unwrap(); ctx.cipher_final_vec(&mut ciphertext).unwrap(); - Base64::encode(&ciphertext) + format!("+OK {}", Base64::encode(&ciphertext)) } - pub fn decrypt(&self, input: &[u8]) -> String { + fn decrypt_ecb(&self, input: &[u8]) -> String { let cipher = Cipher::bf_ecb(); let mut ctx = CipherCtx::new().unwrap(); ctx.decrypt_init(Some(cipher), Some(&self.key), None).unwrap(); ctx.set_padding(false); - let decoded_input = Base64::decode(input); + assert_eq!("+OK ".to_string(), String::from_utf8(input[0..4].to_vec()).unwrap()); + let trimmed_input = input[4..].to_vec(); + let decoded_input = Base64::decode(&trimmed_input); let mut cleartext = vec![]; ctx.cipher_update_vec(&decoded_input, &mut cleartext).unwrap(); ctx.cipher_final_vec(&mut cleartext).unwrap(); @@ -116,30 +164,18 @@ impl Fish { } } -fn main() { - let key = b"chaveULTRAgulosa"; - let input_str = "Bla bla bla isto é um teste glorioso com çedilhas"; - - let fish = Fish::new(key); - - let encrypted = fish.encrypt(input_str.as_bytes()); - println!("Encrypted: {:?}", encrypted); - let decrypted = fish.decrypt(encrypted.as_bytes()); - println!("Decrypted: {:?}", decrypted); -} - #[cfg(test)] mod tests { - use crate::Fish; + use crate::{Fish, Mode}; #[test] fn test_outputs() { - const key: &[u8; 16] = b"chaveULTRAgulosa"; // 16 bytes + const KEY: &[u8; 16] = b"chaveULTRAgulosa"; // 16 bytes let tests: Vec<(&str, &str)> = vec![ - ("teste123", "JnA.b1aNucr0"), - ("Viva o Benfica", "hM/iu.YKqsh.VBpjd.JVc./."), - ("Bla bla bla isto é um teste glorioso com çedilhas", "btrH009AJRe/BBXyV05B2Kl0vEBgI//5zan/eUod11aEtPk1H7rgY.EWjo214MysN/LjuMg.tTbc3.NOurS.") + ("teste123", "+OK JnA.b1aNucr0"), + ("Viva o Benfica", "+OK hM/iu.YKqsh.VBpjd.JVc./."), + ("Bla bla bla isto é um teste glorioso com çedilhas", "+OK btrH009AJRe/BBXyV05B2Kl0vEBgI//5zan/eUod11aEtPk1H7rgY.EWjo214MysN/LjuMg.tTbc3.NOurS.") ]; - let fish = Fish::new(key); + let fish = Fish::new(KEY, Mode::ECB); for test in tests { assert_eq!(fish.encrypt(test.0.as_bytes()), test.1); @@ -148,13 +184,13 @@ mod tests { #[test] fn test_inputs() { - const key: &[u8; 16] = b"chaveULTRAgulosa"; // 16 bytes + const KEY: &[u8; 16] = b"chaveULTRAgulosa"; // 16 bytes let tests: Vec<(&str, &str)> = vec![ - ("teste123", "JnA.b1aNucr0"), - ("Viva o Benfica", "hM/iu.YKqsh.VBpjd.JVc./."), - ("Bla bla bla isto é um teste glorioso com çedilhas", "btrH009AJRe/BBXyV05B2Kl0vEBgI//5zan/eUod11aEtPk1H7rgY.EWjo214MysN/LjuMg.tTbc3.NOurS.") + ("teste123", "+OK JnA.b1aNucr0"), + ("Viva o Benfica", "+OK hM/iu.YKqsh.VBpjd.JVc./."), + ("Bla bla bla isto é um teste glorioso com çedilhas", "+OK btrH009AJRe/BBXyV05B2Kl0vEBgI//5zan/eUod11aEtPk1H7rgY.EWjo214MysN/LjuMg.tTbc3.NOurS.") ]; - let fish = Fish::new(key); + let fish = Fish::new(KEY, Mode::ECB); for test in tests { assert_eq!(fish.decrypt(test.1.as_bytes()), test.0);