Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: malept/crypto-hash
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.1.0
Choose a base ref
...
head repository: malept/crypto-hash
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Jun 27, 2016

  1. Copy the full SHA
    fa76e32 View commit details
  2. Copy the full SHA
    32d21e4 View commit details
  3. Add crates.io badge

    [ci skip]
    malept committed Jun 27, 2016
    Copy the full SHA
    111c4bf View commit details

Commits on Jul 2, 2016

  1. Copy the full SHA
    dd89e4e View commit details
  2. Copy the full SHA
    701a8c4 View commit details

Commits on Sep 24, 2016

  1. Upgrade to openssl 0.8

    malept committed Sep 24, 2016
    Copy the full SHA
    0368a03 View commit details

Commits on Sep 28, 2016

  1. Copy the full SHA
    5cfc6ee View commit details
  2. Copy the full SHA
    3f34caf View commit details

Commits on Nov 6, 2016

  1. Upgrade to rust-openssl 0.9

    malept committed Nov 6, 2016
    Copy the full SHA
    6854e42 View commit details
  2. Travis: Remove 32-bit OSX from the build matrix

    Almost no one actually runs it anyway.
    malept committed Nov 6, 2016
    Copy the full SHA
    816c51a View commit details
  3. Copy the full SHA
    ba3c380 View commit details
  4. Copy the full SHA
    217c739 View commit details

Commits on Nov 7, 2016

  1. Add check-i686 to Makefile

    [ci skip]
    malept committed Nov 7, 2016
    Copy the full SHA
    3709b59 View commit details
  2. Release 0.2.0

    malept committed Nov 7, 2016
    Copy the full SHA
    166b624 View commit details

Commits on Dec 13, 2016

  1. Use the commoncrypto crate

    malept committed Dec 13, 2016
    Copy the full SHA
    ef448d7 View commit details
  2. Link to the crypto libraries being used

    [ci skip]
    malept committed Dec 13, 2016
    Copy the full SHA
    60173a2 View commit details
  3. Release 0.2.1

    malept committed Dec 13, 2016
    Copy the full SHA
    bc3bb3f View commit details

Commits on Dec 24, 2016

  1. Fix clippy markdown warnings

    malept committed Dec 24, 2016
    Copy the full SHA
    2e01ce3 View commit details

Commits on May 8, 2017

  1. Copy the full SHA
    e0880fa View commit details
  2. Add badges to Cargo metadata

    malept committed May 8, 2017
    Copy the full SHA
    7435c43 View commit details
  3. Update commoncrypto to 0.2

    malept committed May 8, 2017
    Copy the full SHA
    fca631c View commit details
  4. Copy the full SHA
    fbd77ee View commit details
  5. Rustfmt

    malept committed May 8, 2017
    Copy the full SHA
    4109d9a View commit details
  6. Update clippy setup

    malept committed May 8, 2017
    Copy the full SHA
    8f062cb View commit details

Commits on May 9, 2017

  1. Travis: run cargo fmt

    malept committed May 9, 2017
    Copy the full SHA
    1f8aa7f View commit details
  2. Travis: cache pip

    malept committed May 9, 2017
    Copy the full SHA
    89b677b View commit details
  3. Copy the full SHA
    81a2a7e View commit details
  4. Copy the full SHA
    11a8d2e View commit details

Commits on Jun 13, 2017

  1. Copy the full SHA
    9e188b5 View commit details
  2. Copy the full SHA
    7f043ba View commit details
  3. Travis: use Trusty containers

    malept committed Jun 13, 2017
    Copy the full SHA
    a1f35a9 View commit details
  4. Travis: debug strange error

    malept committed Jun 13, 2017
    Copy the full SHA
    fef97bb View commit details
  5. Fix clippy warnings

    Breaking change: `data` argument to `*digest()` is `&[u8]` instead
    of `Vec<u8>`.
    malept committed Jun 13, 2017
    Copy the full SHA
    cc7a085 View commit details
  6. Rustfmt

    malept committed Jun 13, 2017
    Copy the full SHA
    8992aa0 View commit details

Commits on Jun 18, 2017

  1. Release 0.3.0

    malept committed Jun 18, 2017
    Copy the full SHA
    c5f5cb1 View commit details
  2. Rustfmt

    malept committed Jun 18, 2017
    Copy the full SHA
    150919a View commit details

Commits on Jun 19, 2017

  1. Fix docs

    malept committed Jun 19, 2017
    Copy the full SHA
    6c6c0bb View commit details
  2. Run stable rustfmt

    malept committed Jun 19, 2017
    Copy the full SHA
    4fbe5a1 View commit details
  3. Fix NEWS link

    [ci skip]
    malept committed Jun 19, 2017
    Copy the full SHA
    0a26f75 View commit details

Commits on Jul 4, 2017

  1. Fix 'make lint'

    malept committed Jul 4, 2017
    Copy the full SHA
    86e2926 View commit details

Commits on Jul 11, 2017

  1. Copy the full SHA
    65ecb7d View commit details

Commits on Nov 27, 2017

  1. Upgrade to hex 0.3

    malept committed Nov 27, 2017
    Copy the full SHA
    7036d94 View commit details
  2. Pin AppVeyor status badge to master

    [ci skip]
    malept committed Nov 27, 2017
    Copy the full SHA
    e8584e8 View commit details

Commits on Feb 13, 2018

  1. Copy the full SHA
    13d20ce View commit details

Commits on Feb 14, 2018

  1. AppVeyor: cleanup config

    malept committed Feb 14, 2018
    Copy the full SHA
    3903e02 View commit details
  2. rustfmt

    malept committed Feb 14, 2018
    Copy the full SHA
    5a33fb6 View commit details
  3. Copy the full SHA
    ede7f42 View commit details
  4. Merge pull request #2 from malept/fixup-ci

    Fixup CI
    malept authored Feb 14, 2018
    Copy the full SHA
    018e392 View commit details
  5. deps: update openssl to 0.10

    Signed-off-by: Alexandra Nikandrova <rage.iz.me@gmail.com>
    ragevou authored and malept committed Feb 14, 2018
    Copy the full SHA
    15f6ea9 View commit details
  6. Merge pull request #1 from ragevou/openssl-v0.10

    deps: update openssl to 0.10
    malept authored Feb 14, 2018
    Copy the full SHA
    1363daf View commit details
Showing with 436 additions and 523 deletions.
  1. +21 −28 .appveyor.yml
  2. +2 −0 .github/FUNDING.yml
  3. +11 −0 .github/dependabot.yml
  4. +84 −95 .travis.yml
  5. +12 −16 Cargo.toml
  6. +7 −2 Makefile
  7. +68 −4 NEWS.md
  8. +6 −4 README.md
  9. +6 −8 ci/after_success.sh
  10. +0 −34 ci/before_install.sh
  11. +0 −12 ci/before_script.sh
  12. +53 −0 ci/install.sh
  13. +33 −10 ci/script.sh
  14. +20 −245 src/imp/commoncrypto.rs
  15. +48 −27 src/imp/cryptoapi.rs
  16. +17 −8 src/imp/openssl.rs
  17. +23 −21 src/lib.rs
  18. +25 −9 src/test.rs
49 changes: 21 additions & 28 deletions .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Based on the "trust" template v0.1.2
# https://github.com/japaric/trust/tree/v0.1.2

platform:
- x86
- x64
@@ -7,10 +10,6 @@ environment:
BUILD_TARGET: msvc
- RUST_VERSION: stable
BUILD_TARGET: gnu
- RUST_VERSION: beta
BUILD_TARGET: msvc
- RUST_VERSION: beta
BUILD_TARGET: gnu
- RUST_VERSION: nightly
BUILD_TARGET: msvc
- RUST_VERSION: nightly
@@ -20,46 +19,40 @@ matrix:
- BUILD_TARGET: msvc
platform: x86
- RUST_VERSION: nightly
branches:
only:
- master
- /v\d+\.\d+\.\d+/
cache:
- target\debug\build
- target\debug\deps
- '%USERPROFILE%\.cargo'
- target
- '%USERPROFILE%\.cargo\registry'
install:
- ps: |
$env:PATH += ";C:\rust\bin";
$env:PATH += ";${env:USERPROFILE}\.cargo\bin";
if ($env:platform -eq 'x86') {
$arch_expanded = "i686-pc-windows-${env:BUILD_TARGET}";
$env:RUST_ARCH = "i686-pc-windows-${env:BUILD_TARGET}";
$env:ARCH = "x86";
$env:bits = "32";
} else {
$arch_expanded = "x86_64-pc-windows-${env:BUILD_TARGET}";
$env:RUST_ARCH = "x86_64-pc-windows-${env:BUILD_TARGET}";
$env:ARCH = "amd64";
$env:bits ="64";
}
if ($env:BUILD_TARGET -eq 'gnu') {
$env:PATH += ";C:\msys64\mingw${env:bits}\bin";
gcc --version;
}
if ($env:RUST_VERSION -eq 'stable') {
echo "Downloading $channel channel manifest";
$manifest = "${env:Temp}\channel-rust-stable";
Start-FileDownload "https://static.rust-lang.org/dist/channel-rust-stable" -FileName "$manifest";
# Search the manifest lines for the correct filename based on expanded arch
$match = Get-Content "$manifest" | Select-String -pattern "${arch_expanded}.exe" -simplematch;
if (!$match -or !$match.line) {
throw "Could not find ${arch_expanded} in stable channel manifest";
}
$env:rust_installer = $match.line;
} else {
$env:rust_installer = "rust-${env:RUST_VERSION}-${arch_expanded}.exe";
}
- curl --show-error --location --retry 5 --output rust-installer.exe https://static.rust-lang.org/dist/%rust_installer%
- .\rust-installer.exe /VERYSILENT /NORESTART /DIR="C:\rust"
- curl --fail --retry 3 --silent --show-error --location -o rustup-init.exe https://win.rustup.rs
- rustup-init.exe --default-host %RUST_ARCH% --default-toolchain %RUST_VERSION% -y
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%
- rustc -vV
- cargo -vV
build: false
test_script:
- cargo test --verbose --no-default-features
# we don't run the "test phase" when doing deploys
- if [%APPVEYOR_REPO_TAG%]==[false] (
cargo build --target %RUST_ARCH% &&
cargo build --target %RUST_ARCH% --release &&
cargo test --target %RUST_ARCH% &&
cargo test --target %RUST_ARCH% --release
)
2 changes: 2 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github: malept
tidelift: cargo/crypto-hash
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
179 changes: 84 additions & 95 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,113 +1,102 @@
sudo: false
# Based on the "trust" template v0.1.2
# https://github.com/japaric/trust/tree/v0.1.2

language: rust
os: linux
dist: bionic
rust: stable

# necessary for `travis-cargo coveralls --no-sudo`
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
- binutils-dev # needed for --verify
cache: cargo

os:
- linux
- osx
jobs:
include:
# rustdoc/rustfmt/clippy
- stage: style-docs
name: "Docs/Formatting/Lints"
env: TARGET=all-style-docs

cache:
apt: true
cargo: true
# Android
- stage: compile-only
env: TARGET=aarch64-linux-android DISABLE_TESTS=1
- env: TARGET=arm-linux-androideabi DISABLE_TESTS=1
- env: TARGET=armv7-linux-androideabi DISABLE_TESTS=1
- env: TARGET=i686-linux-android DISABLE_TESTS=1
- env: TARGET=x86_64-linux-android DISABLE_TESTS=1

rust:
- nightly
- beta
- stable
# *BSD
- env: TARGET=x86_64-unknown-netbsd DISABLE_TESTS=1

# From https://github.com/japaric/rust-everywhere
matrix:
# Clear the whole matrix
exclude:
- os: linux
- os: osx
- rust: nightly
- rust: beta
- rust: stable
include:
- os: linux # 32-bit Linux (glibc)
rust: stable
env: TARGET=i686-unknown-linux-gnu
addons:
apt:
packages:
- libcurl4-gnutls-dev # different curl to not conflict with i386 openssl
- libelf-dev
- libdw-dev
- binutils-dev # needed for --verify
- gcc-multilib # Cross compiler and cross compiled C libraries
- libssl-dev:i386
- os: linux # 32-bit Linux (glibc)
env: TARGET=i686-unknown-linux-gnu
rust: beta
addons:
apt:
packages:
- libcurl4-gnutls-dev # different curl to not conflict with i386 openssl
- libelf-dev
# iOS
- env: TARGET=aarch64-apple-ios DISABLE_TESTS=1
os: osx
- env: TARGET=armv7-apple-ios DISABLE_TESTS=1
os: osx
- env: TARGET=armv7s-apple-ios DISABLE_TESTS=1
os: osx
- env: TARGET=i386-apple-ios DISABLE_TESTS=1
os: osx
- env: TARGET=x86_64-apple-ios DISABLE_TESTS=1
os: osx

# Linux
- env: TARGET=s390x-unknown-linux-gnu DISABLE_TESTS=1

- stage: compile-test
env: TARGET=aarch64-unknown-linux-gnu
- env: TARGET=arm-unknown-linux-gnueabi
- env: TARGET=armv7-unknown-linux-gnueabihf
- env: TARGET=i686-unknown-linux-gnu
- env: TARGET=i686-unknown-linux-musl
- env: TARGET=mips-unknown-linux-gnu
- env: TARGET=mips64-unknown-linux-gnuabi64
- env: TARGET=mips64el-unknown-linux-gnuabi64
- env: TARGET=mipsel-unknown-linux-gnu
- env: TARGET=powerpc-unknown-linux-gnu
- env: TARGET=powerpc64-unknown-linux-gnu
- env: TARGET=powerpc64le-unknown-linux-gnu
- env: TARGET=x86_64-unknown-linux-gnu
# necessary for `cargo coveralls`
addons:
apt:
packages:
- binutils-dev
- libcurl4-openssl-dev
- libdw-dev
- binutils-dev # needed for --verify
- gcc-multilib # Cross compiler and cross compiled C libraries
- libssl-dev:i386
- os: linux # 32-bit Linux (glibc)
rust: nightly
env: TARGET=i686-unknown-linux-gnu
addons:
apt:
packages:
- libcurl4-gnutls-dev # different curl to not conflict with i386 openssl
- libelf-dev
- libdw-dev
- binutils-dev # needed for --verify
- gcc-multilib # Cross compiler and cross compiled C libraries
- libssl-dev:i386
- os: linux # 64-bit Linux (glibc)
rust: stable
env: TARGET=x86_64-unknown-linux-gnu
- os: linux # 64-bit Linux (glibc)
rust: beta
env: TARGET=x86_64-unknown-linux-gnu
- os: linux # 64-bit Linux (glibc)
rust: nightly
env: TARGET=x86_64-unknown-linux-gnu
# 64-bit Linux (musl) doesn't work with openssl
- os: osx # 32-bit OSX
rust: stable
env: TARGET=i686-apple-darwin
- os: osx # 32-bit OSX
rust: beta
env: TARGET=i686-apple-darwin
- os: osx # 32-bit OSX
rust: nightly
env: TARGET=i686-apple-darwin
- os: osx # 64-bit OSX
rust: stable
env: TARGET=x86_64-apple-darwin
- os: osx # 64-bit OSX
rust: beta
env: TARGET=x86_64-apple-darwin
- os: osx # 64-bit OSX
rust: nightly
env: TARGET=x86_64-apple-darwin
- libiberty-dev
- env: TARGET=x86_64-unknown-linux-musl

# OSX
- env: TARGET=i686-apple-darwin
os: osx
- env: TARGET=x86_64-apple-darwin
os: osx

# Testing other channels
- env: TARGET=x86_64-unknown-linux-gnu
rust: nightly
- env: TARGET=x86_64-apple-darwin
os: osx
rust: nightly
allow_failures:
- rust: nightly

before_install: ci/before_install.sh
before_script: ci/before_script.sh
branches:
only:
- master
- /^v\d+\.\d+\.\d+/

stages:
- style-docs
- compile-test
- compile-only

install: ci/install.sh
script: ci/script.sh
after_success: ci/after_success.sh

env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE='lint'
- PATH=$HOME/Library/Python/2.7/bin:$HOME/.local/bin:$PATH
- PATH=$HOME/.local/bin:$PATH
# encrypted github token for doc upload
- secure: "ttZL5OpzNMQOHuaTj7cKyl5N24r3HPB0V/ogWt4Ws10t08aGoonlRSLVlUZaTKI9D5CZMthaWbHRczeJ0DO3MFvAyKcMsnBaM+hc04oRAK7GweoOW3AeKGhBGOVljQK47ySa/Bjniky9zejw/8gzHyOeji+Ydb6YwAdgxTqaHGL+5YAoB1CurxdoVZnVaCLLvvsbPsL27YFkOZrYsI51OlTzkoXj783GowgwjTWc6DBzIgtMTokBKkoPIvVRFBHpwrLhX/pvet3bauXrn2WGkl8+Ab5mBOEhwpmz9TkQW47qyWbibpOwkTwf55C7Ecpi1Aix5o21wLKEDdcZgzY72ri7DillNkLgbcIpHGBQpT+P1lK6pmG1G9HzW2bNPn8k0LukEIY8E0Q1kDef7mc4qw5zkMTgyruRi+yd6r9pTXXh1mDTvNc956Rx/fsfHgxhJIk73/IlYNIaDcmMHbyYQ/AeohWaxup45fqNRaK8AbYFm5rV3o6Ce9c+lW2cHm3ssbhQ5T6L8kGyrDO9glEeyvdKsO6lXRc6x0hiwu9msuRyCgDW1iPD0mkXiMYM5MVC3mg/h9E+e0KcjZg1+PaVqnUWHINsGynNJCctzCmfUMb9aufPTAtoYweT7FMTHekaTLhvxjaYxfPsVmi7kL6HaXAVKQf2qZgp/IjI7AtFsaE="
28 changes: 12 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
[package]
name = "crypto-hash"
version = "0.1.0"
version = "0.3.4"
authors = ["Mark Lee"]
description = "A wrapper for OS-level cryptographic hash functions"
documentation = "https://malept.github.io/crypto-hash/"
documentation = "https://docs.rs/crypto-hash"
repository = "https://github.com/malept/crypto-hash"
readme = "README.md"
keywords = ["crypto", "hash", "digest", "md5", "sha256", "sha512"]
keywords = ["crypto", "hash", "digest"]
license = "MIT"
exclude = [
".*.yml",
"ci/*"
]

[features]

lint = ["clippy"]
[badges]
travis-ci = { repository = "malept/crypto-hash" }
appveyor = { repository = "malept/crypto-hash" }

[dependencies]
hex = "0.4"

hex = "0.2"

clippy = { version = "*", optional = true }

[target.'cfg(target_os = "macos")'.dependencies]
libc = "0.2"
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
commoncrypto = "0.2"

[target.'cfg(target_os = "windows")'.dependencies]
advapi32-sys = "0.2"
winapi = "0.2"
winapi = { version = "0.3", features = ["minwindef", "wincrypt"] }

[target.'cfg(not(any(target_os = "windows", target_os = "macos")))'.dependencies]
openssl = "0.7"
[target.'cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))'.dependencies]
openssl = "0.10"
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
CARGO ?= cargo
CARGO_BUILD_TEST = $(CARGO) test --no-run
KCOV ?= kcov
TEST_APP = debug/crypto_hash-*
TEST_APP = debug/crypto_hash-*.exe
WIN_TARGET = x86_64-pc-windows-gnu

build-test:
$(CARGO_BUILD_TEST)

check-i686:
PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu/pkgconfig \
PKG_CONFIG_ALLOW_CROSS=1 \
$(CARGO) test --target i686-unknown-linux-gnu --verbose

check-wine64:
$(CARGO_BUILD_TEST) --target $(WIN_TARGET)
WINEPREFIX=$(HOME)/.local/share/wineprefixes/wine64 wine64 target/$(WIN_TARGET)/$(TEST_APP)
@@ -21,4 +26,4 @@ fmt:
$(CARGO) fmt

lint:
$(CARGO) clippy --features=lint -- -Wclippy-pedantic
$(CARGO) +nightly clippy -- --allow clippy::pedantic
72 changes: 68 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,75 @@
# Changes by Version
# `crypto-hash`: Changes by Version

## Unreleased
## [Unreleased](https://github.com/malept/crypto-hash/compare/v0.3.4...master)

## [0.3.4] - 2019-08-18

[0.3.4]: https://github.com/malept/crypto-hash/compare/v0.3.3...v0.3.4

### Added

* `Copy`, `Eq`, `Hash`, & `PartialEq` derives on `Algorithm` (#11)

## [0.3.3] - 2018-12-20

[0.3.3]: https://github.com/malept/crypto-hash/compare/v0.3.2...v0.3.3

### Changed

* Revert API change (#6)

## [0.3.2] - 2018-12-20

[0.3.2]: https://github.com/malept/crypto-hash/compare/v0.3.1...v0.3.2

**Note: This release was yanked from Cargo due to #6.**

### Added

* iOS support

## [0.3.1] - 2018-02-14

[0.3.1]: https://github.com/malept/crypto-hash/compare/v0.3.0...v0.3.1

### Changed

* Upgrade to `openssl` 0.10.x (#1)
* Upgrade to `winapi` 0.3.x

## [0.3.0] - 2017-06-18

[0.3.0]: https://github.com/malept/crypto-hash/compare/v0.2.1...v0.3.0

### Changed

* Upgrade to `commoncrypto` 0.2.x
* Function signatures for `digest` and `hex_digest` changed to use `&[u8]`, per Clippy

## [0.2.1] - 2016-12-12

[0.2.1]: https://github.com/malept/crypto-hash/compare/v0.2.0...v0.2.1

### Changed

* Move CommonCrypto implementation to its own crate

## [0.2.0] - 2016-11-06

[0.2.0]: https://github.com/malept/crypto-hash/compare/v0.1.0...v0.2.0

### Added

* SHA-1 algorithm

### Changed

* Upgrade rust-openssl to 0.9

## [0.1.0] - 2016-06-26

[0.1.0]: https://github.com/malept/crypto-hash/releases/tag/v0.1.0

This release signifies the minimum amount of algorithms and implementations necessary for
[HTTP digest authentication](https://tools.ietf.org/html/rfc7616).

@@ -20,5 +86,3 @@ Implementations:
* CommonCrypto (OS X)
* CryptoAPI (Windows)
* OpenSSL (Linux/BSD/etc.)

[0.1.0]: https://github.com/malept/crypto-hash/releases/tag/v0.1.0
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# `crypto-hash`

[![Linux/OS X Status](https://travis-ci.org/malept/crypto-hash.svg?branch=master)](https://travis-ci.org/malept/crypto-hash)
[![Windows status](https://ci.appveyor.com/api/projects/status/xwc9nb4633b5n67r?svg=true)](https://ci.appveyor.com/project/malept/crypto-hash)
[![Windows status](https://ci.appveyor.com/api/projects/status/xwc9nb4633b5n67r/branch/master?svg=true)](https://ci.appveyor.com/project/malept/crypto-hash)
[![Crates.io](https://img.shields.io/crates/v/crypto-hash.svg?maxAge=2592000)](https://crates.io/crates/crypto-hash)

`crypto-hash` is a Rust wrapper around OS-level implementations of cryptographic hash functions.

@@ -14,12 +15,13 @@ the given operating system's bundled cryptographic libraries.
By operating system:

* Windows: CryptoAPI
* OS X: CommonCrypto
* Linux/BSD/etc.: OpenSSL
* OS X: [CommonCrypto](https://crates.io/crates/commoncrypto)
* Linux/BSD/etc.: [OpenSSL](https://crates.io/crates/openssl)

## Supported Algorithms

* MD5
* SHA1
* SHA256
* SHA512

@@ -33,7 +35,7 @@ Example:
```rust
use crypto_hash::{Algorithm, hex_digest};

let digest = hex_digest(Algorithm::SHA256, b"crypto-hash".to_vec());
let digest = hex_digest(Algorithm::SHA256, b"crypto-hash");
```

For more examples, consult the [documentation](https://malept.github.io/crypto-hash/).
14 changes: 6 additions & 8 deletions ci/after_success.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#!/bin/bash
#!/bin/bash -e

set -e
if test "$TARGET" = "x86_64-unknown-linux-gnu"; then
if test "$TARGET" = "all-style-docs"; then
# upload the documentation from the build with stable (automatically only actually
# runs on the master branch, not individual PRs)
travis-cargo --only stable doc-upload
# measure code coverage and upload to coveralls.io (the verify
# argument mitigates kcov crashes due to malformed debuginfo, at the
# cost of some speed <https://github.com/huonw/travis-cargo/issues/12>)
travis-cargo --only stable coveralls --no-sudo --verify --exclude-pattern=/test.rs,*.c,openssl-sys
cargo doc-upload
elif test "$TARGET" = "x86_64-unknown-linux-gnu" -a "$TRAVIS_RUST_VERSION" = "stable"; then
cargo tarpaulin --out Xml
bash <(curl -s https://codecov.io/bash)
fi
34 changes: 0 additions & 34 deletions ci/before_install.sh

This file was deleted.

12 changes: 0 additions & 12 deletions ci/before_script.sh

This file was deleted.

53 changes: 53 additions & 0 deletions ci/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash -xe

install_cargo_plugins() {
cargo install cargo-update || echo "cargo-update already installed"
cargo install cargo-travis || echo "cargo-travis already installed"
cargo install cargo-tarpaulin || echo "cargo-tarpaulin already installed"
cargo install-update -a
}

install_style_docs_dependencies() {
rustup component add rustfmt clippy --toolchain=$TRAVIS_RUST_VERSION
install_cargo_plugins
}

install_compile_dependencies() {
# Builds for iOS are done on OSX, but require the specific target to be installed.
case $TARGET in
*-apple-ios)
rustup target install $TARGET
;;
esac

local target=
if [ $TRAVIS_OS_NAME = linux ]; then
target=x86_64-unknown-linux-musl
else
target=x86_64-apple-darwin
fi

# Pinning to v0.1.16 because v0.2 removes openssl from the images
# https://github.com/rust-embedded/cross/pull/322
local tag=v0.1.16
curl -LSfs https://japaric.github.io/trust/install.sh | \
sh -s -- \
--force \
--git rust-embedded/cross \
--tag $tag \
--target $target

if test "$TARGET" = "x86_64-unknown-linux-gnu" -a "$TRAVIS_RUST_VERSION" = "stable"; then
install_cargo_plugins
fi
}

main() {
if test "$TARGET" = "all-style-docs"; then
install_style_docs_dependencies
else
install_compile_dependencies
fi
}

main
43 changes: 33 additions & 10 deletions ci/script.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
#!/bin/bash
#!/bin/bash -xe

# the main build
set -e
build_and_test() {
cross build --target $TARGET
cross build --target $TARGET --release

travis-cargo build -- --target $TARGET
travis-cargo test -- --target $TARGET
if [ -n $DISABLE_TESTS ]; then
return
fi

if test "$TRAVIS_OS_NAME" = "linux" -a "$TARGET" = "x86_64-unknown-linux-gnu"; then
travis-cargo --only stable doc
fi
cross test --target $TARGET
cross test --target $TARGET --release
}

style_and_docs() {
cargo doc

if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
cargo fmt -- --check $(git diff --name-only "$TRAVIS_COMMIT" "$TRAVIS_BRANCH" | grep \.rs$)
else
cargo fmt -- --check $(git show --format= --name-only "$TRAVIS_COMMIT_RANGE" | sort -u | grep \.rs$)
fi

cargo clippy -- --allow clippy::pedantic
}

main() {
if test "$TARGET" = "all-style-docs"; then
style_and_docs
else
build_and_test
fi
}

if test "$TRAVIS_RUST_VERSION" = "nightly"; then
cargo clippy --target $TARGET --features=$TRAVIS_CARGO_NIGHTLY_FEATURE -- -Wclippy_pedantic
# we don't run the "test phase" when doing deploys
if [ -z $TRAVIS_TAG ]; then
main
fi
265 changes: 20 additions & 245 deletions src/imp/commoncrypto.rs
Original file line number Diff line number Diff line change
@@ -20,131 +20,9 @@

//! A cryptographic hash generator dependent upon OSX's `CommonCrypto`.
use libc::{c_int, c_uint, c_ulong, c_ulonglong};
use std::io;
use super::Algorithm;

macro_rules! unsafe_guard {
($e: expr) => {
unsafe {
let r = $e;
assert_eq!(r, 1);
}
}
}

const MD5_CBLOCK: usize = 64;
const MD5_LBLOCK: usize = MD5_CBLOCK / 4;
const MD5_DIGEST_LENGTH: usize = 16;

const SHA_LBLOCK: usize = 16;
const SHA256_DIGEST_LENGTH: usize = 32;
const SHA512_DIGEST_LENGTH: usize = 64;

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_MD5_CTX {
A: c_uint,
B: c_uint,
C: c_uint,
D: c_uint,
Nl: c_uint,
Nh: c_uint,
data: [c_uint; MD5_LBLOCK],
num: c_uint,
}

impl CC_MD5_CTX {
fn new() -> CC_MD5_CTX {
CC_MD5_CTX {
A: 0,
B: 0,
C: 0,
D: 0,
Nl: 0,
Nh: 0,
data: [0 as c_uint; MD5_LBLOCK],
num: 0,
}
}
}

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_SHA256_CTX {
h: [c_ulong; 8],
Nl: c_ulong,
Nh: c_ulong,
data: [c_ulong; SHA_LBLOCK],
num: c_uint,
md_len: c_uint,
}

impl CC_SHA256_CTX {
fn new() -> CC_SHA256_CTX {
CC_SHA256_CTX {
h: [0 as c_ulong; 8],
Nl: 0,
Nh: 0,
data: [0 as c_ulong; SHA_LBLOCK],
num: 0,
md_len: 0,
}
}
}

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_SHA512_CTX {
h: [c_ulonglong; 8],
Nl: c_ulonglong,
Nh: c_ulonglong,
data: [c_ulonglong; SHA_LBLOCK],
num: c_uint,
md_len: c_uint,
}

impl CC_SHA512_CTX {
fn new() -> CC_SHA512_CTX {
CC_SHA512_CTX {
h: [0 as c_ulonglong; 8],
Nl: 0,
Nh: 0,
data: [0 as c_ulonglong; SHA_LBLOCK],
num: 0,
md_len: 0,
}
}
}

#[derive(Debug)]
enum DigestContext {
MD5(CC_MD5_CTX),
SHA256(CC_SHA256_CTX),
SHA512(CC_SHA512_CTX),
}

extern "C" {
fn CC_MD5_Init(ctx: *mut CC_MD5_CTX) -> c_int;
fn CC_MD5_Update(ctx: *mut CC_MD5_CTX, data: *const u8, n: usize) -> c_int;
fn CC_MD5_Final(md: *mut u8, ctx: *mut CC_MD5_CTX) -> c_int;
fn CC_SHA256_Init(ctx: *mut CC_SHA256_CTX) -> c_int;
fn CC_SHA256_Update(ctx: *mut CC_SHA256_CTX, data: *const u8, n: usize) -> c_int;
fn CC_SHA256_Final(md: *mut u8, ctx: *mut CC_SHA256_CTX) -> c_int;
fn CC_SHA512_Init(ctx: *mut CC_SHA512_CTX) -> c_int;
fn CC_SHA512_Update(ctx: *mut CC_SHA512_CTX, data: *const u8, n: usize) -> c_int;
fn CC_SHA512_Final(md: *mut u8, ctx: *mut CC_SHA512_CTX) -> c_int;
}

#[derive(PartialEq, Copy, Clone, Debug)]
enum State {
Reset,
Updated,
Finalized,
}
use commoncrypto::hash;
use std::io;

/// Generator of digests using a cryptographic hash function.
///
@@ -159,148 +37,45 @@ enum State {
/// hasher.write_all(b"-");
/// hasher.write_all(b"hash");
/// let result = hasher.finish();
/// let expected = b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'".to_vec();
/// let expected =
/// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'"
/// .to_vec();
/// assert_eq!(expected, result)
/// ```
#[derive(Debug)]
pub struct Hasher {
context: DigestContext,
state: State,
}

fn md5_new() -> CC_MD5_CTX {
let mut ctx: CC_MD5_CTX = CC_MD5_CTX::new();
md5_init(&mut ctx);
ctx
}

fn md5_init(ctx: &mut CC_MD5_CTX) {
unsafe_guard!(CC_MD5_Init(ctx));
assert!(!(ctx as *mut CC_MD5_CTX).is_null());
}

fn md5_write(ctx: &mut CC_MD5_CTX, buf: &[u8]) {
unsafe_guard!(CC_MD5_Update(ctx, buf.as_ptr(), buf.len()));
}

fn md5_finish(ctx: &mut CC_MD5_CTX) -> Vec<u8> {
let mut md = [0u8; MD5_DIGEST_LENGTH];
unsafe_guard!(CC_MD5_Final(md.as_mut_ptr(), ctx));
md.to_vec()
}

fn sha256_new() -> CC_SHA256_CTX {
let mut ctx: CC_SHA256_CTX = CC_SHA256_CTX::new();
sha256_init(&mut ctx);
ctx
}

fn sha512_new() -> CC_SHA512_CTX {
let mut ctx: CC_SHA512_CTX = CC_SHA512_CTX::new();
sha512_init(&mut ctx);
ctx
}

fn sha256_init(ctx: &mut CC_SHA256_CTX) {
unsafe_guard!(CC_SHA256_Init(ctx));
assert!(!(ctx as *mut CC_SHA256_CTX).is_null());
}

fn sha512_init(ctx: &mut CC_SHA512_CTX) {
unsafe_guard!(CC_SHA512_Init(ctx));
assert!(!(ctx as *mut CC_SHA512_CTX).is_null());
}

fn sha256_write(ctx: &mut CC_SHA256_CTX, buf: &[u8]) {
unsafe_guard!(CC_SHA256_Update(ctx, buf.as_ptr(), buf.len()));
}

fn sha512_write(ctx: &mut CC_SHA512_CTX, buf: &[u8]) {
unsafe_guard!(CC_SHA512_Update(ctx, buf.as_ptr(), buf.len()));
}

fn sha256_finish(ctx: &mut CC_SHA256_CTX) -> Vec<u8> {
let mut md = [0u8; SHA256_DIGEST_LENGTH];
unsafe_guard!(CC_SHA256_Final(md.as_mut_ptr(), ctx));
md.to_vec()
}

fn sha512_finish(ctx: &mut CC_SHA512_CTX) -> Vec<u8> {
let mut md = [0u8; SHA512_DIGEST_LENGTH];
unsafe_guard!(CC_SHA512_Final(md.as_mut_ptr(), ctx));
md.to_vec()
}
pub struct Hasher(hash::Hasher);

impl Hasher {
/// Create a new `Hasher` for the given `Algorithm`.
pub fn new(algorithm: Algorithm) -> Hasher {
let context = match algorithm {
Algorithm::MD5 => DigestContext::MD5(md5_new()),
Algorithm::SHA256 => DigestContext::SHA256(sha256_new()),
Algorithm::SHA512 => DigestContext::SHA512(sha512_new()),
let cc_algorithm = match algorithm {
Algorithm::MD5 => hash::CCDigestAlgorithm::kCCDigestMD5,
Algorithm::SHA1 => hash::CCDigestAlgorithm::kCCDigestSHA1,
Algorithm::SHA256 => hash::CCDigestAlgorithm::kCCDigestSHA256,
Algorithm::SHA512 => hash::CCDigestAlgorithm::kCCDigestSHA512,
};

Hasher {
context: context,
state: State::Reset,
}
}

fn init(&mut self) {
match self.state {
State::Reset => return,
State::Updated => {
self.finish();
}
State::Finalized => (),
}
match self.context {
DigestContext::MD5(ref mut ctx) => md5_init(ctx),
DigestContext::SHA256(ref mut ctx) => sha256_init(ctx),
DigestContext::SHA512(ref mut ctx) => sha512_init(ctx),
}
self.state = State::Reset;
Hasher(hash::Hasher::new(cc_algorithm))
}

/// Generate a digest from the data written to the `Hasher`.
pub fn finish(&mut self) -> Vec<u8> {
if self.state == State::Finalized {
self.init();
let Hasher(ref mut hasher) = *self;
match hasher.finish() {
Ok(digest) => digest,
Err(error) => panic!("CommonCrypto error: {}", error),
}
let result = match self.context {
DigestContext::MD5(ref mut ctx) => md5_finish(ctx),
DigestContext::SHA256(ref mut ctx) => sha256_finish(ctx),
DigestContext::SHA512(ref mut ctx) => sha512_finish(ctx),
};
self.state = State::Finalized;

result
}
}

impl io::Write for Hasher {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.state == State::Finalized {
self.init();
}
match self.context {
DigestContext::MD5(ref mut ctx) => md5_write(ctx, buf),
DigestContext::SHA256(ref mut ctx) => sha256_write(ctx, buf),
DigestContext::SHA512(ref mut ctx) => sha512_write(ctx, buf),
}
self.state = State::Updated;
Ok(buf.len())
let Hasher(ref mut hasher) = *self;
hasher.write(buf)
}

fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

impl Drop for Hasher {
fn drop(&mut self) {
if self.state != State::Finalized {
self.finish();
}
let Hasher(ref mut hasher) = *self;
hasher.flush()
}
}
75 changes: 48 additions & 27 deletions src/imp/cryptoapi.rs
Original file line number Diff line number Diff line change
@@ -24,20 +24,22 @@
//! https://github.com/rust-lang/cargo/blob/0.10.0/src/cargo/util/sha256.rs
//! which is copyright (c) 2014 The Rust Project Developers under the MIT license.
use advapi32::{CryptAcquireContextW, CryptCreateHash, CryptDestroyHash, CryptGetHashParam,
CryptHashData, CryptReleaseContext};
use super::Algorithm;
use std::io;
use std::ptr;
use super::Algorithm;
use winapi::{CALG_MD5, CALG_SHA_256, CALG_SHA_512, CRYPT_SILENT, CRYPT_VERIFYCONTEXT, DWORD,
HCRYPTHASH, HCRYPTPROV, HP_HASHVAL, PROV_RSA_AES};
use winapi::shared::minwindef::DWORD;
use winapi::um::wincrypt::{
CryptAcquireContextW, CryptCreateHash, CryptDestroyHash, CryptGetHashParam, CryptHashData,
CryptReleaseContext, ALG_ID, CALG_MD5, CALG_SHA1, CALG_SHA_256, CALG_SHA_512, CRYPT_SILENT,
CRYPT_VERIFYCONTEXT, HCRYPTHASH, HCRYPTPROV, HP_HASHVAL, PROV_RSA_AES,
};

macro_rules! call {
($e: expr) => ({
($e:expr) => {{
if $e == 0 {
panic!("failed {}: {}", stringify!($e), io::Error::last_os_error())
}
})
}};
}

macro_rules! finish_algorithm {
@@ -55,6 +57,7 @@ macro_rules! finish_algorithm {
}

const MD5_LENGTH: usize = 16;
const SHA1_LENGTH: usize = 20;
const SHA256_LENGTH: usize = 32;
const SHA512_LENGTH: usize = 64;

@@ -71,11 +74,13 @@ const SHA512_LENGTH: usize = 64;
/// hasher.write_all(b"-");
/// hasher.write_all(b"hash");
/// let result = hasher.finish();
/// let expected = b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'".to_vec();
/// let expected =
/// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'"
/// .to_vec();
/// assert_eq!(expected, result)
/// ```
pub struct Hasher {
algorithm: Algorithm,
alg_id: ALG_ID,
hcryptprov: HCRYPTPROV,
hcrypthash: HCRYPTHASH,
}
@@ -85,50 +90,66 @@ impl Hasher {
pub fn new(algorithm: Algorithm) -> Hasher {
let mut hcp = 0;
call!(unsafe {
CryptAcquireContextW(&mut hcp,
ptr::null(),
ptr::null(),
PROV_RSA_AES,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
CryptAcquireContextW(
&mut hcp,
ptr::null(),
ptr::null(),
PROV_RSA_AES,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT,
)
});

let hash_type = match algorithm {
let alg_id = match algorithm {
Algorithm::MD5 => CALG_MD5,
Algorithm::SHA1 => CALG_SHA1,
Algorithm::SHA256 => CALG_SHA_256,
Algorithm::SHA512 => CALG_SHA_512,
};

let mut ret = Hasher {
algorithm: algorithm,
let mut hasher = Hasher {
alg_id,
hcryptprov: hcp,
hcrypthash: 0,
};

call!(unsafe { CryptCreateHash(ret.hcryptprov, hash_type, 0, 0, &mut ret.hcrypthash) });
ret
call!(unsafe {
CryptCreateHash(
hasher.hcryptprov,
hasher.alg_id,
0,
0,
&mut hasher.hcrypthash,
)
});
hasher
}

/// Generate a digest from the data written to the `Hasher`.
pub fn finish(&mut self) -> Vec<u8> {
match self.algorithm {
Algorithm::MD5 => self.finish_md5(),
Algorithm::SHA256 => self.finish_sha256(),
Algorithm::SHA512 => self.finish_sha512(),
match self.alg_id {
CALG_MD5 => self.finish_md5(),
CALG_SHA1 => self.finish_sha1(),
CALG_SHA_256 => self.finish_sha256(),
CALG_SHA_512 => self.finish_sha512(),
_ => panic!("Unknown algorithm {}", self.alg_id),
}
}

finish_algorithm!(finish_md5, MD5_LENGTH);
finish_algorithm!(finish_sha1, SHA1_LENGTH);
finish_algorithm!(finish_sha256, SHA256_LENGTH);
finish_algorithm!(finish_sha512, SHA512_LENGTH);
}

impl io::Write for Hasher {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
call!(unsafe {
CryptHashData(self.hcrypthash,
buf.as_ptr() as *mut _,
buf.len() as DWORD,
0)
CryptHashData(
self.hcrypthash,
buf.as_ptr() as *mut _,
buf.len() as DWORD,
0,
)
});
Ok(buf.len())
}
25 changes: 17 additions & 8 deletions src/imp/openssl.rs
Original file line number Diff line number Diff line change
@@ -22,9 +22,9 @@
#![warn(missing_docs)]

use openssl::crypto::hash;
use std::io;
use super::Algorithm;
use openssl::hash;
use std::io;

/// Generator of digests using a cryptographic hash function.
///
@@ -39,7 +39,9 @@ use super::Algorithm;
/// hasher.write_all(b"-");
/// hasher.write_all(b"hash");
/// let result = hasher.finish();
/// let expected = b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'".to_vec();
/// let expected =
/// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'"
/// .to_vec();
/// assert_eq!(expected, result)
/// ```
pub struct Hasher(hash::Hasher);
@@ -48,18 +50,25 @@ impl Hasher {
/// Create a new `Hasher` for the given `Algorithm`.
pub fn new(algorithm: Algorithm) -> Hasher {
let hash_type = match algorithm {
Algorithm::MD5 => hash::Type::MD5,
Algorithm::SHA256 => hash::Type::SHA256,
Algorithm::SHA512 => hash::Type::SHA512,
Algorithm::MD5 => hash::MessageDigest::md5(),
Algorithm::SHA1 => hash::MessageDigest::sha1(),
Algorithm::SHA256 => hash::MessageDigest::sha256(),
Algorithm::SHA512 => hash::MessageDigest::sha512(),
};

Hasher(hash::Hasher::new(hash_type))
match hash::Hasher::new(hash_type) {
Ok(hasher) => Hasher(hasher),
Err(error_stack) => panic!("OpenSSL error(s): {}", error_stack),
}
}

/// Generate a digest from the data written to the `Hasher`.
pub fn finish(&mut self) -> Vec<u8> {
let Hasher(ref mut hasher) = *self;
hasher.finish()
match hasher.finish() {
Ok(digest) => digest.to_vec(),
Err(error_stack) => panic!("OpenSSL error(s): {}", error_stack),
}
}
}

44 changes: 23 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015, 2016 Mark Lee
// Copyright (c) 2015, 2016, 2017 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
@@ -30,38 +30,36 @@
//!
//! By operating system:
//!
//! * Windows: CryptoAPI
//! * Mac OS X: CommonCrypto
//! * Linux/BSD/etc.: OpenSSL
//! * Windows: `CryptoAPI`
//! * Mac OS X: `CommonCrypto`
//! * Linux/BSD/etc.: `OpenSSL`
//!
//! # Supported Algorithms
//!
//! * MD5
//! * SHA1
//! * SHA256
//! * SHA512
#![warn(missing_docs)]

#[cfg(target_os = "windows")]
extern crate advapi32;
#[cfg(any(target_os = "macos", target_os = "ios"))]
extern crate commoncrypto;
extern crate hex;
#[cfg(target_os = "macos")]
extern crate libc;
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
extern crate openssl;
#[cfg(target_os = "windows")]
extern crate winapi;

use hex::ToHex;
use std::io::Write;

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[path = "imp/commoncrypto.rs"]
mod imp;
#[cfg(target_os = "windows")]
#[path = "imp/cryptoapi.rs"]
mod imp;
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
#[path = "imp/openssl.rs"]
mod imp;

@@ -70,10 +68,12 @@ mod test;
pub use imp::Hasher;

/// Available cryptographic hash functions.
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Algorithm {
/// Popular message digest algorithm, only available for backwards compatibility purposes.
MD5,
/// SHA-1 algorithm from NIST FIPS, only available for backwards compatibility purposes.
SHA1,
/// SHA-2 family algorithm (256 bits).
SHA256,
/// SHA-2 family algorithm (512 bits).
@@ -88,14 +88,16 @@ pub enum Algorithm {
/// ```rust
/// use crypto_hash::{Algorithm, digest};
///
/// let data = b"crypto-hash".to_vec();
/// let data = b"crypto-hash";
/// let result = digest(Algorithm::SHA256, data);
/// let expected = b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'".to_vec();
/// let expected =
/// b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'"
/// .to_vec();
/// assert_eq!(expected, result)
/// ```
pub fn digest(algorithm: Algorithm, data: Vec<u8>) -> Vec<u8> {
let mut hasher = imp::Hasher::new(algorithm.clone());
hasher.write_all(&data[..]).expect("Could not write hash data");
pub fn digest(algorithm: Algorithm, data: &[u8]) -> Vec<u8> {
let mut hasher = imp::Hasher::new(algorithm);
hasher.write_all(data).expect("Could not write hash data");
hasher.finish()
}

@@ -107,11 +109,11 @@ pub fn digest(algorithm: Algorithm, data: Vec<u8>) -> Vec<u8> {
/// ```rust
/// use crypto_hash::{Algorithm, hex_digest};
///
/// let data = b"crypto-hash".to_vec();
/// let data = b"crypto-hash";
/// let result = hex_digest(Algorithm::SHA256, data);
/// let expected = "fd1afb6022cd4d47c890961c533928eacfe8219f1b2524f7fb2a61847ddf8c27";
/// assert_eq!(expected, result)
/// ```
pub fn hex_digest(algorithm: Algorithm, data: Vec<u8>) -> String {
digest(algorithm, data).to_hex()
pub fn hex_digest(algorithm: Algorithm, data: &[u8]) -> String {
hex::encode(digest(algorithm, data))
}
34 changes: 25 additions & 9 deletions src/test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016 Mark Lee
// Copyright (c) 2016, 2017 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
@@ -20,14 +20,22 @@

#![cfg(test)]

use hex::ToHex;
use super::{hex_digest, Algorithm, Hasher};
use hex;
use std::io::Write;
use super::{Algorithm, Hasher, hex_digest};

// From Wikipedia
const MD5_EMPTY_STRING: &'static str = "d41d8cd98f00b204e9800998ecf8427e";
const SHA256_EMPTY_STRING: &'static str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
const SHA512_EMPTY_STRING: &'static str = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e";
const SHA1_EMPTY_STRING: &'static str = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
const SHA256_EMPTY_STRING: &'static str = concat!(
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649",
"b934ca495991b7852b855"
);
const SHA512_EMPTY_STRING: &'static str = concat!(
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5",
"715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318",
"d2877eec2f63b931bd47417a81a538327af927da3e"
);
const TO_HASH: &'static str = "The quick brown fox jumps over the lazy dog";
const TO_HASH_MD5: &'static str = "9e107d9d372bb6826bd81d3542a419d6";

@@ -36,6 +44,11 @@ fn md5_empty_string() {
assert_hex_hashed_empty_string(Algorithm::MD5, MD5_EMPTY_STRING)
}

#[test]
fn sha1_empty_string() {
assert_hex_hashed_empty_string(Algorithm::SHA1, SHA1_EMPTY_STRING)
}

#[test]
fn sha256_empty_string() {
// From Wikipedia
@@ -50,18 +63,21 @@ fn sha512_empty_string() {
#[test]
fn hasher_sans_write() {
let mut hasher = Hasher::new(Algorithm::MD5);
let actual = hasher.finish().to_hex();
let actual = hex::encode(hasher.finish());
assert_eq!(MD5_EMPTY_STRING, actual)
}

#[test]
fn hasher_with_write() {
let mut hasher = Hasher::new(Algorithm::MD5);
hasher.write_all(TO_HASH.as_bytes()).expect("Could not write to hasher");
let actual = hasher.finish().to_hex();
hasher
.write_all(TO_HASH.as_bytes())
.expect("Could not write to hasher");
let actual = hex::encode(hasher.finish());
assert_eq!(TO_HASH_MD5, actual)
}

fn assert_hex_hashed_empty_string(algorithm: Algorithm, expected: &str) {
assert_eq!(expected, hex_digest(algorithm, vec![]).as_str())
let vec = vec![];
assert_eq!(expected, hex_digest(algorithm, vec.as_slice()).as_str())
}