From 07773d8fee23ab31ac1fed917ddcc102f07aa9db Mon Sep 17 00:00:00 2001 From: lloyd Date: Mon, 11 Mar 2013 20:44:16 +0100 Subject: [PATCH] Add support for HMAC, RC4, AES-128, hex encoding, etc --- Makefile | 7 +++++ hex.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ hmac.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 Makefile create mode 100644 hex.rs create mode 100644 hmac.rs diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..2d55d237 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +crypto: crypto.rc $(wildcard *.rs) + rustc crypto.rc + rustc --test crypto.rc + +clean: + rm -f crypto libcrypto-*.so diff --git a/hex.rs b/hex.rs new file mode 100644 index 00000000..ca422a49 --- /dev/null +++ b/hex.rs @@ -0,0 +1,91 @@ +/* + * Copyright 2013 Jack Lloyd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +extern mod std; + +pub trait ToHex { + pure fn to_hex() -> ~str; +} + +impl &[u8]: ToHex { + pure fn to_hex() -> ~str { + + let chars = str::chars(~"0123456789ABCDEF"); + + let mut s = ~""; + + for uint::range(0, self.len()) |i| { + + let x = self[i]; + + let xhi = (x >> 4) & 0x0F; + let xlo = (x ) & 0x0F; + + unsafe { + str::push_char(&mut s, chars[xhi]); + str::push_char(&mut s, chars[xlo]); + } + } + + s + } +} + +pub trait FromHex { + pure fn from_hex() -> ~[u8]; +} + +impl &str: FromHex { + pure fn from_hex() -> ~[u8] { + let mut vec = vec::with_capacity(self.len() / 2); + + for str::each_chari(self) |i,c| { + + let nibble = + if c >= '0' && c <= '9' { (c as u8) - 0x30 } + else if c >= 'a' && c <= 'f' { (c as u8) - (0x61 - 10) } + else if c >= 'A' && c <= 'F' { (c as u8) - (0x41 - 10) } + else { fail ~"bad hex character"; }; + + if i % 2 == 0 { + unsafe { + vec::push(&mut vec, nibble << 4); + } + } + else { + vec[i/2] |= nibble; + } + } + + vec + } +} + +#[cfg(test)] +mod tests { + + #[test] + pub fn test() { + + assert [05u8, 0xffu8, 0x00u8, 0x59u8].to_hex() == ~"05FF0059"; + + assert "00FFA9D1F5".from_hex() == ~[0, 0xff, 0xa9, 0xd1, 0xf5]; + + assert "00FFA9D1F5".from_hex().to_hex() == ~"00FFA9D1F5"; + } + + +} \ No newline at end of file diff --git a/hmac.rs b/hmac.rs new file mode 100644 index 00000000..1dc40344 --- /dev/null +++ b/hmac.rs @@ -0,0 +1,92 @@ +/* + * Copyright 2013 Jack Lloyd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use hash::*; + +#[allow(non_camel_case_types)] +struct HMAC_CTX { + mut md: EVP_MD, + mut md_ctx: EVP_MD_CTX, + mut i_ctx: EVP_MD_CTX, + mut o_ctx: EVP_MD_CTX, + mut key_length: libc::c_uint, + mut key: [libc::c_uchar * 128] +} + +#[link_name = "crypto"] +#[abi = "cdecl"] +extern mod libcrypto { + + fn HMAC_CTX_init(ctx: *mut HMAC_CTX, key: *u8, keylen: libc::c_int, md: EVP_MD); + + fn HMAC_Update(ctx: *mut HMAC_CTX, input: *u8, len: libc::c_uint); + + fn HMAC_Final(ctx: *mut HMAC_CTX, output: *mut u8, len: *mut libc::c_uint); +} + +pub struct HMAC { + priv mut ctx: HMAC_CTX, + priv len: uint, +} + +pub fn HMAC(ht: HashType, key: ~[u8]) -> HMAC { + unsafe { + + let (evp, mdlen) = evpmd(ht); + + let mut ctx : HMAC_CTX = HMAC_CTX { + mut md: ptr::null(), + mut md_ctx: ptr::null(), + mut i_ctx: ptr::null(), + mut o_ctx: ptr::null(), + mut key_length: 0, + mut key: [0u8, .. 128] + }; + + libcrypto::HMAC_CTX_init(&mut ctx, + vec::raw::to_ptr(key), + key.len() as libc::c_int, + evp); + + HMAC { ctx: ctx, len: mdlen } + } +} + +pub impl HMAC { + fn update(data: &[u8]) unsafe { + do vec::as_imm_buf(data) |pdata, len| { + libcrypto::HMAC_Update(&mut self.ctx, pdata, len as libc::c_uint) + } + } + + fn final() -> ~[u8] unsafe { + let mut res = vec::from_elem(self.len, 0u8); + let mut outlen: libc::c_uint = 0; + do vec::as_mut_buf(res) |pres, _len| { + libcrypto::HMAC_Final(&mut self.ctx, pres, &mut outlen); + assert self.len == outlen as uint + } + res + } +} + +fn main() { + let h = HMAC(SHA512, ~[00u8]); + + h.update(~[00u8]); + + io::println(fmt!("%?", h.final())) +}