{"action":"created","issue":{"url":"https://api.github.com/repos/sfackler/rust-openssl/issues/141","labels_url":"https://api.github.com/repos/sfackler/rust-openssl/issues/141/labels{/name}","comments_url":"https://api.github.com/repos/sfackler/rust-openssl/issues/141/comments","events_url":"https://api.github.com/repos/sfackler/rust-openssl/issues/141/events","html_url":"https://github.com/sfackler/rust-openssl/pull/141","id":54046303,"number":141,"title":"Improve Hasher and HMAC APIs","user":{"login":"gkoz","id":4260361,"avatar_url":"https://avatars.githubusercontent.com/u/4260361?v=3","gravatar_id":"","url":"https://api.github.com/users/gkoz","html_url":"https://github.com/gkoz","followers_url":"https://api.github.com/users/gkoz/followers","following_url":"https://api.github.com/users/gkoz/following{/other_user}","gists_url":"https://api.github.com/users/gkoz/gists{/gist_id}","starred_url":"https://api.github.com/users/gkoz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gkoz/subscriptions","organizations_url":"https://api.github.com/users/gkoz/orgs","repos_url":"https://api.github.com/users/gkoz/repos","events_url":"https://api.github.com/users/gkoz/events{/privacy}","received_events_url":"https://api.github.com/users/gkoz/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-01-12T12:04:56Z","updated_at":"2015-01-20T20:39:27Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/sfackler/rust-openssl/pulls/141","html_url":"https://github.com/sfackler/rust-openssl/pull/141","diff_url":"https://github.com/sfackler/rust-openssl/pull/141.diff","patch_url":"https://github.com/sfackler/rust-openssl/pull/141.patch"},"body":"The reuse API I implemented for Hasher the last time proved to be very hard to use. Here's a better approach that relies on the borrow checker by using a mut reference. This time it's both Hasher and HMAC.\r\n\r\n- Add a \"one stop\" compute() method for the simple use case.\r\n- Split out update()/finalize() API into the Accumulator struct.\r\n- Rely on borrow checker to enforce openssl call order contract (init, update+, finalize).\r\n- Track the lifecycle explicitly as an optimization in HMAC case and to workaround Rust 1.0's unsafe destructor limitation (see https://github.com/rust-lang/rust/issues/17858#issuecomment-58280941).\r\n- Unify Hasher and HMAC implementation details for consistency.\r\n- Implement Writer for Accumulator.\r\n- Add examples.\r\n- Deprecate standalone hash() in favor of Hasher::compute().\r\n\r\nNote that Accumulator now has very similar methods update() and write(). It could make sense to drop update(), although write() requires checking the return value..."},"comment":{"url":"https://api.github.com/repos/sfackler/rust-openssl/issues/comments/70728508","html_url":"https://github.com/sfackler/rust-openssl/pull/141#issuecomment-70728508","issue_url":"https://api.github.com/repos/sfackler/rust-openssl/issues/141","id":70728508,"user":{"login":"gkoz","id":4260361,"avatar_url":"https://avatars.githubusercontent.com/u/4260361?v=3","gravatar_id":"","url":"https://api.github.com/users/gkoz","html_url":"https://github.com/gkoz","followers_url":"https://api.github.com/users/gkoz/followers","following_url":"https://api.github.com/users/gkoz/following{/other_user}","gists_url":"https://api.github.com/users/gkoz/gists{/gist_id}","starred_url":"https://api.github.com/users/gkoz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gkoz/subscriptions","organizations_url":"https://api.github.com/users/gkoz/orgs","repos_url":"https://api.github.com/users/gkoz/repos","events_url":"https://api.github.com/users/gkoz/events{/privacy}","received_events_url":"https://api.github.com/users/gkoz/received_events","type":"User","site_admin":false},"created_at":"2015-01-20T20:39:27Z","updated_at":"2015-01-20T20:39:27Z","body":"The way Hash is implemented for &str and &[T] makes me question this idea: it mixes extra data into the input so the Hasher results would be incompatible with everyone else.\r\n```rust\r\nimpl<S: Writer + Hasher> Hash<S> for str {\r\n    #[inline]\r\n    fn hash(&self, state: &mut S) {\r\n        state.write(self.as_bytes());\r\n        0xffu8.hash(state)\r\n    }\r\n}\r\nimpl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {\r\n    #[inline]\r\n    fn hash(&self, state: &mut S) {\r\n        self.len().hash(state);\r\n        for elt in self.iter() {\r\n            elt.hash(state);\r\n        }\r\n    }\r\n}\r\n```"}}