Skip to content

Instantly share code, notes, and snippets.

@vincascm
Last active August 20, 2024 19:13
Show Gist options
  • Save vincascm/fda1cff664fa027937a53446ba8ef605 to your computer and use it in GitHub Desktop.
Save vincascm/fda1cff664fa027937a53446ba8ef605 to your computer and use it in GitHub Desktop.
triple des(3des) ecb pkcs5 padding encrypt/decrypt function for rust, use openssl crypto library.
//! triple des(3des) ecb pkcs5 padding encrypt/decrypt function for rust, use openssl crypto
//! library.
//! refer to <http://blog.csdn.net/lyjinger/article/details/1722570>
//! coded by vinoca.
//! 2017.11.24
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
extern crate libc;
use libc::c_uchar;
pub type DES_cblock = [c_uchar; 8];
pub type const_DES_cblock = [c_uchar; 8];
pub type DES_LONG = libc::c_ulong;
#[repr(C)]
#[derive(Default, Debug)]
pub struct DES_key_schedule {
ks: [DES_cblock; 16],
}
#[link(name = "crypto")]
extern {
fn DES_set_key_unchecked(block_key: *const c_uchar, ks: *mut DES_key_schedule);
fn DES_ecb3_encrypt(input: *const c_uchar, output: *mut c_uchar,
ks1: *const DES_key_schedule,
ks2: *const DES_key_schedule,
ks3: *const DES_key_schedule,
enc: libc::c_int,
);
}
pub const Encrypt: i32 = 1;
pub const Decrypt: i32 = 0;
pub fn des_ecb3(data: &[u8], key: &str, mode:i32) -> Vec<u8> {
// pad data
let mut data = data.to_vec();
let mut pad = 8 - data.len() % 8;
if pad == 8 {
pad = 0;
}
for _ in 0..pad {
data.push(pad as u8);
}
// pad key
let mut key = key.as_bytes().to_vec();
key.truncate(24);
for _ in 0..24 - key.len() {
key.push(0);
}
let mut ks = Vec::new();
for _ in 0..3 {
ks.push(DES_key_schedule::default());
}
let mut out_block = vec![0u8; 8];
let mut output = Box::new(Vec::with_capacity(data.len()));
unsafe {
for (i, item) in key.chunks(8).enumerate() {
DES_set_key_unchecked(item.as_ptr(), &mut ks[i]);
}
for i in data.chunks(8) {
DES_ecb3_encrypt(i.as_ptr(), out_block.as_mut_ptr(), &ks[0], &ks[1], &ks[2], mode);
output.extend_from_slice(out_block.as_slice());
}
}
if mode == Decrypt {
let pad = *output.last().unwrap();
(*output).truncate(data.len() - pad as usize);
*output
} else {
*output
}
}
#[cfg(test)]
mod tests {
use super::{Encrypt, Decrypt, des_ecb3};
#[test]
fn test_des_ecb3() {
let data = "hello world!";
let key = "01234567899876543210";
let e = des_ecb3(&data.as_bytes(), &key, Encrypt);
let d = des_ecb3(&e, &key, Decrypt);
println!("{:?}", d);
//println!("{:?}", std::str::from_utf8(&d).unwrap());
}
}
@coyksdev
Copy link

Hello. Thanks, I am trying to use this gist. do you have an idea about this error?

note: ld: library not found for -lcrypto
clang: error: linker command failed with exit code 1 (use -v to see invocation)

@vincascm
Copy link
Author

requires OpenSSL to be installed,
but you can use openssl directly https://docs.rs/openssl/0.10.42/openssl/cipher/struct.Cipher.html#method.des_ede3

@coyksdev
Copy link

Thanks, I was able to run it. Sorry, I am a beginner in rust. is there a way to get the string representation of the encrypted value?

I tried code below but throws Result::unwrap() on an Err value: Utf8Error { valid_up_to: 1, error_len: Some(1) }'`

println!("{:?}", std::str::from_utf8(&e).unwrap());

@coyksdev
Copy link

coyksdev commented Oct 3, 2022

Hi @vincascm, how do i make it pkcs7?

@robertoduessmann
Copy link

Thanks for the snippet @vincascm . Have you happen to work or have something similar for CBC mode?

@vincascm
Copy link
Author

just like this:

use openssl::symm::{decrypt, encrypt, Cipher};

fn main() {
    let cipher = Cipher::des_ede3_cbc();
    let text = b"Some Crypto Text";
    let key = b"012345678998765432101234";
    assert_eq!(key.len(), 24);
    let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
    let data = encrypt(cipher, key, Some(iv), text).unwrap();
    let ciphertext = decrypt(cipher, key, Some(iv), &data).unwrap();
    assert_eq!(text, &ciphertext[..]);
}

@robertoduessmann
Copy link

Thanks a bunch @vincascm 💪

@ppsilv
Copy link

ppsilv commented Aug 20, 2024

@vincascm Thank you very much, I was already getting angry with Rust because all the codes I took as examples (because I'm just starting out with Rust) were not simple to do a simple thing, because the complexity in encryption is in the library and not in our code, but it seems to me that those who are developing in Rust are unaware of this. Your code is perfect, it encrypts and decrypts directly without any fuss. CONGRATULATIONS, I hope many Rust developers see your code and see what it's like to really develop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment