Last active
August 20, 2024 19:13
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! 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()); | |
} | |
} |
Hi @vincascm, how do i make it pkcs7?
Thanks for the snippet @vincascm . Have you happen to work or have something similar for CBC mode?
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[..]);
}
Thanks a bunch @vincascm 💪
@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
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 anErr
value: Utf8Error { valid_up_to: 1, error_len: Some(1) }'`println!("{:?}", std::str::from_utf8(&e).unwrap());