Repository: RustCrypto/hashes (language: rust)

Issue:
Expose sha1::compress publicly?
I'm trying to accomplish the following task on [this project](https://github.com/not-an-aardvark/lucky-commit):

1. Using the `sha-1` crate, run sha1 on a few blocks of data, once, without finalizing.
2. Save the sha1 state vector from step (1)
3. Run a different implementation of sha1 (e.g. within a GPU) on a small number of remaining blocks, using the state vector from (2) as an initial state.

This is a bit difficult to do with the `sha-1` library. Since a `Sha1` struct doesn't expose its internal state (the `h` field), it's not possible to copy the state from step 2 and use it elsewhere. Additionally, since the `Sha1` struct is the only entrypoint to the crate, I also can't use `sha1::compress` to keep track of state while buffering the data manually. My current workaround is to depend on the `sha1-asm` crate, which [does expose the `compress` API I need](https://docs.rs/sha1-asm/0.5.0/sha1_asm/fn.compress.html). But this isn't ideal, because I lose support for the `sha-1` crate's implementation that uses SHA1 intrinsics, as well as its software implementation of `compress` for architectures that don't support the assembly version.

Admittedly, this is a very unusual use case, so it would be understandable if the answer is to just fork the repo. But since `sha1::compress` is a fairly well-established primitive and is already implemented, I thought I would ask it you'd be open to making it accessible from outside the crate.


Discussion / hints:
It's fine. We have a `compress` feature in the `sha2` crate for similar reasons:

https://github.com/RustCrypto/hashes/blob/c5fbbc5/sha2/src/lib.rs#L70-L71
Yes, exposing the compression function like we did in `sha2` should be simple enough. Also note that in `digest v0.10` we will expose [block-level APIs](https://docs.rs/digest/0.10.0-pre.3/digest/core_api/index.html) (you probably will be most interested in the `UpdateCore` trait), together with additional inherent getters for retrieving hasher state I think should cover your use-case.

Fix patch:
diff --git a/.github/workflows/sha1.yml b/.github/workflows/sha1.yml
index 9baefe689..2eeadd6b4 100644
--- a/.github/workflows/sha1.yml
+++ b/.github/workflows/sha1.yml
@@ -54,3 +54,4 @@ jobs:
       - run: cargo test --no-default-features
       - run: cargo test
       - run: cargo test --features asm
+      - run: cargo test --all-features
diff --git a/Cargo.lock b/Cargo.lock
index 48a3e882d..f136f496e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -223,7 +223,7 @@ dependencies = [
 
 [[package]]
 name = "sha-1"
-version = "0.9.3"
+version = "0.9.4"
 dependencies = [
  "block-buffer",
  "cfg-if",
diff --git a/sha1/CHANGELOG.md b/sha1/CHANGELOG.md
index 335ad2d89..44c7c1a92 100644
--- a/sha1/CHANGELOG.md
+++ b/sha1/CHANGELOG.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## 0.9.4 (2021-02-16)
+### Added
+- Expose compression function under the `compress` feature flag. ([#238])
+
+[#238]: https://github.com/RustCrypto/hashes/pull/238
+
 ## 0.9.3 (2021-02-01)
 ### Changed
 - Use SHA1 intrinsics when `asm` feature is enabled. ([#225])
diff --git a/sha1/Cargo.toml b/sha1/Cargo.toml
index aa9a90bbd..8b4141895 100644
--- a/sha1/Cargo.toml
+++ b/sha1/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sha-1"
-version = "0.9.3"
+version = "0.9.4"
 description = "SHA-1 hash function"
 authors = ["RustCrypto Developers"]
 license = "MIT OR Apache-2.0"
@@ -35,8 +35,12 @@ hex-literal = "0.2"
 default = ["std"]
 std = ["digest/std"]
 asm = ["sha1-asm", "libc"]
-# Force software implementation
-force-soft = []
+compress = [] # Expose compress function
+force-soft = [] # Force software implementation
 
 # DEPRECATED: use `asm` instead
 asm-aarch64 = ["asm"]
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
diff --git a/sha1/src/compress.rs b/sha1/src/compress.rs
index 1370bf84e..6817ab589 100644
--- a/sha1/src/compress.rs
+++ b/sha1/src/compress.rs
@@ -28,6 +28,8 @@ cfg_if::cfg_if! {
     }
 }
 
+/// SHA-1 compression function
+#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
 pub fn compress(state: &mut [u32; 5], blocks: &[GenericArray<u8, U64>]) {
     // SAFETY: GenericArray<u8, U64> and [u8; 64] have
     // exactly the same memory layout
diff --git a/sha1/src/lib.rs b/sha1/src/lib.rs
index 3ad62ce86..52efb11bf 100644
--- a/sha1/src/lib.rs
+++ b/sha1/src/lib.rs
@@ -24,6 +24,7 @@
 //! [2]: https://github.com/RustCrypto/hashes
 
 #![no_std]
+#![cfg_attr(docsrs, feature(doc_cfg))]
 #![doc(
     html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
     html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
@@ -37,6 +38,9 @@ extern crate std;
 mod compress;
 mod consts;
 
+#[cfg(feature = "compress")]
+pub use crate::compress::compress;
+#[cfg(not(feature = "compress"))]
 use crate::compress::compress;
 use crate::consts::{H, STATE_LEN};
 use block_buffer::BlockBuffer;


Test patch: