208 lines
6.1 KiB
Rust
208 lines
6.1 KiB
Rust
#![feature(unique)]
|
|
#![allow(dead_code)]
|
|
extern crate libc;
|
|
use std::mem;
|
|
use std::ptr;
|
|
|
|
#[repr(C)]
|
|
#[allow(non_snake_case)]
|
|
struct SHA_CTX {
|
|
h0: libc::c_uint,
|
|
h1: libc::c_uint,
|
|
h2: libc::c_uint,
|
|
h3: libc::c_uint,
|
|
h4: libc::c_uint,
|
|
N1: libc::c_uint,
|
|
NH: libc::c_uint,
|
|
data: [libc::c_uint; 16],
|
|
num: libc::c_uint
|
|
}
|
|
|
|
enum RSA{}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
enum EVP_CIPHER_CTX{}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
enum EVP_CIPHER{}
|
|
|
|
enum ENGINE{}
|
|
|
|
const RSA_PKCS1_PADDING : libc::c_int = 1;
|
|
|
|
extern {
|
|
fn SHA1_Init(c: *mut SHA_CTX) -> libc::c_int;
|
|
fn SHA1_Update(c: *mut SHA_CTX, data: *const u8, len: libc::size_t) -> libc::c_int;
|
|
fn SHA1_Final(md: *const u8, c: *mut SHA_CTX) -> libc::c_int;
|
|
|
|
fn d2i_RSA_PUBKEY(a: *mut *mut RSA, data: *const *const u8, len: libc::c_int) -> *mut RSA;
|
|
fn RSA_free(rsa: *mut RSA);
|
|
fn RSA_size(rsa: *mut RSA) -> libc::c_int;
|
|
fn RSA_public_encrypt(flen: libc::c_int, from: *const u8, to: *mut u8, rsa: *mut RSA, padding: libc::c_int) -> libc::c_int;
|
|
|
|
fn RAND_bytes(buf: *mut u8, len: libc::c_int) -> libc::c_int;
|
|
|
|
fn EVP_CIPHER_CTX_init(a: *mut EVP_CIPHER_CTX);
|
|
fn EVP_EncryptInit_ex(ctx: *mut EVP_CIPHER_CTX, cipher: *const EVP_CIPHER, engine: *mut ENGINE, key: *const u8, iv: *const u8) -> libc::c_int;
|
|
fn EVP_DecryptInit_ex(ctx: *mut EVP_CIPHER_CTX, cipher: *const EVP_CIPHER, engine: *mut ENGINE, key: *const u8, iv: *const u8) -> libc::c_int;
|
|
fn EVP_EncryptUpdate(ctx: *mut EVP_CIPHER_CTX, out: *mut u8, outl: *mut libc::c_int, input: *const u8, inl: libc::c_int) -> libc::c_int;
|
|
fn EVP_DecryptUpdate(ctx: *mut EVP_CIPHER_CTX, out: *mut u8, outl: *mut libc::c_int, input: *const u8, inl: libc::c_int) -> libc::c_int;
|
|
fn EVP_aes_128_cfb8() -> *const EVP_CIPHER;
|
|
fn EVP_CIPHER_block_size(cipher: *const EVP_CIPHER) -> libc::c_int;
|
|
fn EVP_CIPHER_CTX_free(ctx: *mut EVP_CIPHER_CTX);
|
|
fn EVP_CIPHER_CTX_cleanup(ctx: *mut EVP_CIPHER_CTX) -> libc::c_int;
|
|
fn EVP_CIPHER_CTX_new() -> *mut EVP_CIPHER_CTX;
|
|
}
|
|
|
|
pub struct EVPCipher {
|
|
internal: ptr::Unique<EVP_CIPHER_CTX>,
|
|
|
|
block_size: usize,
|
|
}
|
|
|
|
impl EVPCipher {
|
|
pub fn new(key: &[u8], iv: &[u8], decrypt: bool) -> EVPCipher {
|
|
unsafe {
|
|
let mut e = EVPCipher {
|
|
internal: ptr::Unique::new(EVP_CIPHER_CTX_new()),
|
|
block_size: EVP_CIPHER_block_size(EVP_aes_128_cfb8()) as usize,
|
|
};
|
|
EVP_CIPHER_CTX_init(e.internal.get_mut());
|
|
if decrypt {
|
|
if EVP_DecryptInit_ex(e.internal.get_mut(), EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 {
|
|
panic!("Init error");
|
|
}
|
|
} else {
|
|
if EVP_EncryptInit_ex(e.internal.get_mut(), EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 {
|
|
panic!("Init error");
|
|
}
|
|
}
|
|
e
|
|
}
|
|
}
|
|
|
|
pub fn decrypt(&mut self, data: &[u8]) -> Vec<u8> {
|
|
unsafe {
|
|
let mut out = Vec::with_capacity(data.len());
|
|
let mut out_len: libc::c_int = 0;
|
|
if EVP_DecryptUpdate(self.internal.get_mut(), out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 {
|
|
panic!("Decrypt error")
|
|
}
|
|
out.set_len(out_len as usize);
|
|
out
|
|
}
|
|
}
|
|
|
|
pub fn encrypt(&mut self, data: &[u8]) -> Vec<u8> {
|
|
unsafe {
|
|
let mut out = Vec::with_capacity(data.len());
|
|
let mut out_len: libc::c_int = 0;
|
|
if EVP_EncryptUpdate(self.internal.get_mut(), out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 {
|
|
panic!("Encrypt error")
|
|
}
|
|
out.set_len(out_len as usize);
|
|
out
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl Drop for EVPCipher {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
EVP_CIPHER_CTX_cleanup(self.internal.get_mut());
|
|
EVP_CIPHER_CTX_free(self.internal.get_mut());
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn gen_random(len: usize) -> Vec<u8> {
|
|
unsafe {
|
|
let mut data = Vec::with_capacity(len);
|
|
data.set_len(len);
|
|
RAND_bytes(data.as_mut_ptr(), len as libc::c_int);
|
|
data
|
|
}
|
|
}
|
|
|
|
|
|
pub struct PublicKey {
|
|
rsa: *mut RSA
|
|
}
|
|
|
|
impl PublicKey {
|
|
pub fn new(data: &[u8]) -> PublicKey {
|
|
unsafe {
|
|
let cert = d2i_RSA_PUBKEY(ptr::null_mut(), &data.as_ptr(), data.len() as libc::c_int);
|
|
if cert.is_null() {
|
|
panic!("Error");
|
|
}
|
|
PublicKey { rsa: cert }
|
|
}
|
|
}
|
|
|
|
pub fn encrypt(&mut self, data: &Vec<u8>) -> Vec<u8> {
|
|
unsafe {
|
|
let size = RSA_size(self.rsa) as usize;
|
|
let mut out = Vec::with_capacity(size);
|
|
out.set_len(size);
|
|
RSA_public_encrypt(data.len() as libc::c_int, data.as_ptr(), out.as_mut_ptr(), self.rsa, RSA_PKCS1_PADDING);
|
|
out
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for PublicKey {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
RSA_free(self.rsa);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct SHA1 {
|
|
internal: SHA_CTX,
|
|
}
|
|
|
|
impl SHA1 {
|
|
pub fn new() -> SHA1 {
|
|
unsafe {
|
|
let mut s : SHA1 = mem::uninitialized();
|
|
if SHA1_Init(&mut s.internal) == 0 {
|
|
panic!("error init sha1");
|
|
}
|
|
s
|
|
}
|
|
}
|
|
|
|
pub fn update(&mut self, data: &[u8]) {
|
|
unsafe {
|
|
if SHA1_Update(&mut self.internal, data.as_ptr(), data.len() as libc::size_t) == 0 {
|
|
panic!("sha1 error");
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn bytes(mut self) -> Vec<u8> {
|
|
unsafe {
|
|
let mut dst = Vec::with_capacity(20);
|
|
dst.set_len(20);
|
|
if SHA1_Final(dst.as_mut_ptr(), &mut self.internal) == 0 {
|
|
panic!("sha1 error");
|
|
}
|
|
dst
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::{SHA1};
|
|
#[test]
|
|
fn test_sha1() {
|
|
let mut sha1 = SHA1::new();
|
|
sha1.update(b"Hello world");
|
|
assert!(sha1.bytes().iter().map(|b| format!("{:02X}", b)).collect::<Vec<String>>().connect("") == "7B502C3A1F48C8609AE212CDFB639DEE39673F5E");
|
|
}
|
|
}
|