commoncrypto-0.2.0/Cargo.toml01006440001750000175000000002010130415752630014412 0ustar0000000000000000# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "commoncrypto" version = "0.2.0" authors = ["Mark Lee"] description = "Idiomatic Rust wrappers for Mac OS X's CommonCrypto library" documentation = "https://docs.rs/commoncrypto" keywords = ["crypto", "hash", "digest", "osx", "commoncrypto"] license = "MIT" repository = "https://github.com/malept/rust-commoncrypto" [dependencies.clippy] version = "0.0" optional = true [dependencies.commoncrypto-sys] version = "0.2.0" [dev-dependencies.hex] version = "0.2" [features] lint = ["clippy"] commoncrypto-0.2.0/Cargo.toml.orig01006440001750000175000000001022130415752630015353 0ustar0000000000000000[package] name = "commoncrypto" version = "0.2.0" authors = ["Mark Lee"] description = "Idiomatic Rust wrappers for Mac OS X's CommonCrypto library" documentation = "https://docs.rs/commoncrypto" repository = "https://github.com/malept/rust-commoncrypto" keywords = ["crypto", "hash", "digest", "osx", "commoncrypto"] license = "MIT" [features] lint = ["clippy"] [dependencies] commoncrypto-sys = { version = "0.2.0", path = "../commoncrypto-sys" } clippy = { version = "0.0", optional = true } [dev-dependencies] hex = "0.2" commoncrypto-0.2.0/src/hash.rs01006440001750000175000000007661130234164270014557 0ustar0000000000000000// Copyright (c) 2016 Mark Lee // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. //! Idiomatic Rust wrapper for `CommonCrypto`'s `CCDigestCtx` struct. use commoncrypto_sys::{CCDigestCreate, CCDigestCtx, CCDigestDestroy, CCDigestFinal, CCDigestGetOutputSizeFromRef, CCDigestReset, CCDigestUpdate}; use std::io; pub use commoncrypto_sys::CCDigestAlgorithm; const MAX_DIGEST_SIZE: usize = 64; macro_rules! err_from_ccdigest_retval{ ($func_name: expr, $val: expr) => { Err(io::Error::new(io::ErrorKind::Other, format!("{} returned nonzero: {}", $func_name, $val))) } } #[derive(PartialEq, Copy, Clone, Debug)] enum State { Reset, Updated, Finalized, } /// Generates cryptographic hashes. #[derive(Debug)] pub struct Hasher { ctx: *mut CCDigestCtx, state: State, } impl Hasher { /// Creates a new `Hasher` which will use the given cryptographic `algorithm`. pub fn new(algorithm: CCDigestAlgorithm) -> Hasher { let ctx: *mut CCDigestCtx; unsafe { ctx = CCDigestCreate(algorithm); } Hasher { ctx: ctx, state: State::Reset, } } fn init(&mut self) { match self.state { State::Reset => return, State::Updated => { let _ = self.finish(); } State::Finalized => (), } unsafe { CCDigestReset(self.ctx) }; self.state = State::Reset; } /// Feeds data into the hasher. pub fn update(&mut self, data: &[u8]) -> io::Result { if self.state == State::Finalized { self.init(); } let result = unsafe { CCDigestUpdate(self.ctx, data.as_ptr() as *mut _, data.len()) }; if result == 0 { self.state = State::Updated; Ok(data.len()) } else { err_from_ccdigest_retval!("CCDigestCreate", result) } } /// Finalizes digest operations and produces the digest output. pub fn finish(&mut self) -> io::Result> { if self.state == State::Finalized { self.init(); } let expected_len = unsafe { CCDigestGetOutputSizeFromRef(self.ctx) }; let mut md = vec![0; MAX_DIGEST_SIZE]; let result = unsafe { CCDigestFinal(self.ctx, md.as_mut_ptr()) }; if result == 0 { self.state = State::Finalized; md.truncate(expected_len); Ok(md) } else { err_from_ccdigest_retval!("CCDigestFinal", result) } } } impl io::Write for Hasher { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.update(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } impl Drop for Hasher { fn drop(&mut self) { if self.state != State::Finalized { let _ = self.finish(); } unsafe { CCDigestDestroy(self.ctx) } } } commoncrypto-0.2.0/src/lib.rs01006440001750000175000000002417130415752510014375 0ustar0000000000000000// Copyright (c) 2016 Mark Lee // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. //! Idiomatic Rust wrappers for `CommonCrypto` structs. #![warn(missing_docs)] extern crate commoncrypto_sys; #[warn(missing_docs)] pub mod hash; #[warn(missing_docs)] pub mod pbkdf2; commoncrypto-0.2.0/src/pbkdf2.rs01006440001750000175000000005046130415752510015000 0ustar0000000000000000// Copyright (c) 2016 // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. //! Idiomatic Rust wrapper for `CommonCrypto`'s `CCKeyDerivationPBKDF` function. use commoncrypto_sys::{CCKeyDerivationPBKDF, CCPBKDFAlgorithm}; use std::io; pub use commoncrypto_sys::CCPseudoRandomAlgorithm; macro_rules! err_from_cckeyderivationpbkdf_retval { ($func_name: expr, $val: expr) => {{ let kind = match $val { // kCCParamError is the only one that's specifically noted -43000 => io::ErrorKind::InvalidInput, _ => io::ErrorKind::Other, }; Err(io::Error::new(kind, format!("{} returned nonzero: {}", $func_name, $val))) }} } /// Derive a key from a password or passphrase and a salt pub fn pbkdf2(password: &[u8], salt: &[u8], prf: CCPseudoRandomAlgorithm, rounds: u32, key_len: usize) -> io::Result> { let mut pw_derived = vec![0u8; key_len]; let result = unsafe { CCKeyDerivationPBKDF(CCPBKDFAlgorithm::kCCPBKDF2, password.as_ptr(), password.len(), salt.as_ptr(), salt.len(), prf, rounds, pw_derived.as_mut_ptr(), pw_derived.len()) }; if result == 0 { Ok(pw_derived) } else { err_from_cckeyderivationpbkdf_retval!("CCKeyDerivationPBKDF", result) } } commoncrypto-0.2.0/tests/hash.rs01006440001750000175000000001070130234170140015107 0ustar0000000000000000extern crate commoncrypto; extern crate hex; use commoncrypto::hash::{CCDigestAlgorithm, Hasher}; use hex::ToHex; use std::io::Write; const TO_HASH: &'static str = "The quick brown fox jumps over the lazy dog"; const TO_HASH_MD5: &'static str = "9e107d9d372bb6826bd81d3542a419d6"; #[test] fn md5_hasher() { let mut hasher = Hasher::new(CCDigestAlgorithm::kCCDigestMD5); assert!(hasher.write_all(TO_HASH.as_bytes()).is_ok()); let result = hasher.finish(); assert!(result.is_ok()); assert_eq!(result.expect("Hash failed").to_hex(), TO_HASH_MD5) } commoncrypto-0.2.0/tests/pbkdf2.rs01006440001750000175000000000702130415752510015345 0ustar0000000000000000extern crate commoncrypto; extern crate hex; use commoncrypto::pbkdf2::{pbkdf2, CCPseudoRandomAlgorithm}; use hex::ToHex; #[test] fn derive_pbkdf2() { let derived = pbkdf2(b"password", b"salt", CCPseudoRandomAlgorithm::kCCPRFHmacAlgSHA1, 1, 20) .unwrap(); assert_eq!("0c60c80f961f0e71f3a9b524af6012062fe037a6", derived.to_hex()); }