Turn project into a Rust library.

Create two methods to called from a C program.
Use cbindgen to generate Header file.
Add a basic rfish.c for testing.
Added Basic Makefile.
This commit is contained in:
Pedro de Oliveira 2023-08-12 16:41:54 +01:00
parent 9eb29a31ec
commit e843c65e17
Signed by: falso
GPG Key ID: 1E4F05ACDBB2C85C
7 changed files with 488 additions and 34 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
/target
/.idea/
rfish.iml
rfish.iml
rfish.h
main

369
Cargo.lock generated
View File

@ -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"

View File

@ -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"

17
Makefile Normal file
View File

@ -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

14
build.rs Normal file
View File

@ -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");
}

20
rfish.c Normal file
View File

@ -0,0 +1,20 @@
#include <stdio.h>
#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;
}

View File

@ -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<u8>,
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<u8> {
@ -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);