-
-
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. | |
//! 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()); | |
} | |
} |
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
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());
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.
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)