You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2018/07/16 20:44:42 UTC

[couchdb] branch master updated: Make MD5 hash implementation configurable (#1171)

This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 3acf15f  Make MD5 hash implementation configurable (#1171)
3acf15f is described below

commit 3acf15f7f16e09d50eb96a99893f3cbe7a9d2d1d
Author: rokek <82...@users.noreply.github.com>
AuthorDate: Mon Jul 16 15:38:07 2018 -0400

    Make MD5 hash implementation configurable (#1171)
---
 configure                                          |  9 +++++
 src/chttpd/src/chttpd.erl                          |  2 +-
 src/couch/rebar.config.script                      |  9 ++++-
 src/couch/src/couch_bt_engine.erl                  |  2 +-
 src/couch/src/couch_db.erl                         |  2 +-
 src/couch/src/couch_file.erl                       |  8 ++--
 src/couch/src/couch_hash.erl                       | 45 ++++++++++++++++++++++
 src/couch/src/couch_httpd.erl                      |  2 +-
 src/couch/src/couch_native_process.erl             |  4 +-
 src/couch/src/couch_stream.erl                     | 18 ++++-----
 src/couch/src/test_engine_util.erl                 |  8 ++--
 src/couch/test/couchdb_attachments_tests.erl       |  6 +--
 src/couch_epi/src/couch_epi_data.erl               |  2 +-
 src/couch_epi/src/couch_epi_util.erl               |  2 +-
 .../test/couch_index_ddoc_updated_tests.erl        |  2 +-
 src/couch_mrview/src/couch_mrview.erl              |  2 +-
 src/couch_mrview/src/couch_mrview_util.erl         |  8 ++--
 src/couch_replicator/src/couch_replicator_ids.erl  |  2 +-
 .../test/couch_replicator_many_leaves_tests.erl    |  2 +-
 .../test/couch_replicator_test_helper.erl          | 12 +++---
 src/mem3/src/mem3_rep.erl                          |  6 +--
 21 files changed, 107 insertions(+), 46 deletions(-)

diff --git a/configure b/configure
index fa0dfed..370c964 100755
--- a/configure
+++ b/configure
@@ -25,6 +25,7 @@ PACKAGE_AUTHOR_NAME="The Apache Software Foundation"
 WITH_CURL="false"
 WITH_FAUXTON=1
 WITH_DOCS=1
+ERLANG_MD5="false"
 SKIP_DEPS=0
 
 COUCHDB_USER="$(whoami 2>/dev/null || echo couchdb)"
@@ -46,6 +47,7 @@ Options:
   -c | --with-curl            request that couchjs is linked to cURL (default false)
   --disable-fauxton           do not build Fauxton
   --disable-docs              do not build any documentation or manpages
+  --erlang-md5                use erlang for md5 hash operations
   --dev                       alias for --with-curl --disable-docs --disable-fauxton
   --skip-deps                 do not update erlang dependencies
   --rebar=PATH                use rebar by specified path (version >=2.6.0 && <3.0 required)
@@ -78,6 +80,12 @@ parse_opts() {
                 continue
                 ;;
 
+            --erlang-md5)
+                ERLANG_MD5="true"
+                shift
+                continue
+                ;;
+
             --dev)
                 WITH_DOCS=0
                 WITH_FAUXTON=0
@@ -195,6 +203,7 @@ EOF
 
 cat > $rootdir/config.erl << EOF
 {with_curl, $WITH_CURL}.
+{erlang_md5, $ERLANG_MD5}.
 EOF
 
 install_local_rebar() {
diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index c0179ba..a562839 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -681,7 +681,7 @@ doc_etag(#doc{id=Id, body=Body, revs={Start, [DiskRev|_]}}) ->
     couch_httpd:doc_etag(Id, Body, {Start, DiskRev}).
 
 make_etag(Term) ->
-    <<SigInt:128/integer>> = crypto:hash(md5, term_to_binary(Term)),
+    <<SigInt:128/integer>> = couch_hash:md5_hash(term_to_binary(Term)),
     list_to_binary(io_lib:format("\"~.36B\"",[SigInt])).
 
 etag_match(Req, CurrentEtag) when is_binary(CurrentEtag) ->
diff --git a/src/couch/rebar.config.script b/src/couch/rebar.config.script
index 498ce3a..fe249d0 100644
--- a/src/couch/rebar.config.script
+++ b/src/couch/rebar.config.script
@@ -64,6 +64,13 @@ ConfigSrc = [["#define ", K, " ", V, $\n] || {K, V} <- ConfigH],
 ConfigBin = iolist_to_binary(ConfigSrc),
 ok = CopyIfDifferent(CouchJSConfig, ConfigBin),
 
+MD5Config = case lists:keyfind(erlang_md5, 1, CouchConfig) of
+    {erlang_md5, true} ->
+        [{d, 'ERLANG_MD5', true}];
+    {erlang_md5, false} ->
+        []
+end,
+
 %% TODO support curl on Windows
 {JS_CFLAGS, JS_LDFLAGS} = case lists:keyfind(with_curl, 1, CouchConfig) of
     {with_curl, true} ->
@@ -143,7 +150,7 @@ AddConfig = [
     {erl_opts, PlatformDefines ++ [
         {d, 'COUCHDB_VERSION', Version},
         {i, "../"}
-    ]},
+    ] ++ MD5Config},
     {eunit_compile_opts, PlatformDefines}
 ].
 
diff --git a/src/couch/src/couch_bt_engine.erl b/src/couch/src/couch_bt_engine.erl
index a42d116..ee0d6d8 100644
--- a/src/couch/src/couch_bt_engine.erl
+++ b/src/couch/src/couch_bt_engine.erl
@@ -330,7 +330,7 @@ serialize_doc(#st{} = St, #doc{} = Doc) ->
     Body = Compress(Doc#doc.body),
     Atts = Compress(Doc#doc.atts),
     SummaryBin = ?term_to_bin({Body, Atts}),
-    Md5 = crypto:hash(md5, SummaryBin),
+    Md5 = couch_hash:md5_hash(SummaryBin),
     Data = couch_file:assemble_file_chunk(SummaryBin, Md5),
     % TODO: This is a terrible hack to get around the issues
     %       in COUCHDB-3255. We'll need to come back and figure
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index b47cc7e..65ca54a 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -938,7 +938,7 @@ new_revid(#doc{body=Body, revs={OldStart,OldRevs}, atts=Atts, deleted=Deleted})
             ?l2b(integer_to_list(couch_util:rand32()));
         Atts2 ->
             OldRev = case OldRevs of [] -> 0; [OldRev0|_] -> OldRev0 end,
-            crypto:hash(md5, term_to_binary([Deleted, OldStart, OldRev, Body, Atts2], [{minor_version, 1}]))
+            couch_hash:md5_hash(term_to_binary([Deleted, OldStart, OldRev, Body, Atts2], [{minor_version, 1}]))
     end.
 
 new_revs([], OutBuckets, IdRevsAcc) ->
diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl
index 9f668ea..55cb956 100644
--- a/src/couch/src/couch_file.erl
+++ b/src/couch/src/couch_file.erl
@@ -132,7 +132,7 @@ append_binary(Fd, Bin) ->
     
 append_binary_md5(Fd, Bin) ->
     ioq:call(Fd,
-        {append_bin, assemble_file_chunk(Bin, crypto:hash(md5, Bin))},
+        {append_bin, assemble_file_chunk(Bin, couch_hash:md5_hash(Bin))},
         erlang:get(io_priority)).
 
 append_raw_chunk(Fd, Chunk) ->
@@ -175,7 +175,7 @@ pread_iolist(Fd, Pos) ->
     {ok, IoList, <<>>} ->
         {ok, IoList};
     {ok, IoList, Md5} ->
-        case crypto:hash(md5, IoList) of
+        case couch_hash:md5_hash(IoList) of
         Md5 ->
             {ok, IoList};
         _ ->
@@ -333,7 +333,7 @@ read_header(Fd) ->
 
 write_header(Fd, Data) ->
     Bin = term_to_binary(Data),
-    Md5 = crypto:hash(md5, Bin),
+    Md5 = couch_hash:md5_hash(Bin),
     % now we assemble the final header binary and write to disk
     FinalBin = <<Md5/binary, Bin/binary>>,
     ioq:call(Fd, {write_header, FinalBin}, erlang:get(io_priority)).
@@ -559,7 +559,7 @@ load_header(Fd, Pos, HeaderLen, RestBlock) ->
     end,
     <<Md5Sig:16/binary, HeaderBin/binary>> =
         iolist_to_binary(remove_block_prefixes(?PREFIX_SIZE, RawBin)),
-    Md5Sig = crypto:hash(md5, HeaderBin),
+    Md5Sig = couch_hash:md5_hash(HeaderBin),
     {ok, HeaderBin}.
 
 
diff --git a/src/couch/src/couch_hash.erl b/src/couch/src/couch_hash.erl
new file mode 100644
index 0000000..842b374
--- /dev/null
+++ b/src/couch/src/couch_hash.erl
@@ -0,0 +1,45 @@
+% 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.
+
+-module(couch_hash).
+
+-export([md5_hash/1, md5_hash_final/1, md5_hash_init/0, md5_hash_update/2]).
+
+-ifdef(ERLANG_MD5).
+
+md5_hash(Data) ->
+    erlang:md5(Data).
+
+md5_hash_final(Context) ->
+    erlang:md5_final(Context).
+
+md5_hash_init() ->
+    erlang:md5_init().
+
+md5_hash_update(Context, Data) ->
+    erlang:md5_update(Context, Data).
+
+-else.
+
+md5_hash(Data) ->
+    crypto:hash(md5, Data).
+
+md5_hash_final(Context) ->
+    crypto:hash_final(Context).
+
+md5_hash_init() ->
+    crypto:hash_init(md5).
+
+md5_hash_update(Context, Data) ->
+    crypto:hash_update(Context, Data).
+
+-endif.
diff --git a/src/couch/src/couch_httpd.erl b/src/couch/src/couch_httpd.erl
index 050282a..a8cfca6 100644
--- a/src/couch/src/couch_httpd.erl
+++ b/src/couch/src/couch_httpd.erl
@@ -622,7 +622,7 @@ rev_etag({Start, DiskRev}) ->
      <<$", Rev/binary, $">>.
 
 make_etag(Term) ->
-    <<SigInt:128/integer>> = crypto:hash(md5, term_to_binary(Term)),
+    <<SigInt:128/integer>> = couch_hash:md5_hash(term_to_binary(Term)),
     iolist_to_binary([$", io_lib:format("~.36B", [SigInt]), $"]).
 
 etag_match(Req, CurrentEtag) when is_binary(CurrentEtag) ->
diff --git a/src/couch/src/couch_native_process.erl b/src/couch/src/couch_native_process.erl
index 8f8ce8b..eee8b28 100644
--- a/src/couch/src/couch_native_process.erl
+++ b/src/couch/src/couch_native_process.erl
@@ -363,11 +363,11 @@ bindings(State, Sig, DDoc) ->
 % thanks to erlview, via:
 % http://erlang.org/pipermail/erlang-questions/2003-November/010544.html
 makefun(State, Source) ->
-    Sig = crypto:hash(md5, Source),
+    Sig = couch_hash:md5_hash(Source),
     BindFuns = bindings(State, Sig),
     {Sig, makefun(State, Source, BindFuns)}.
 makefun(State, Source, {DDoc}) ->
-    Sig = crypto:hash(md5, lists:flatten([Source, term_to_binary(DDoc)])),
+    Sig = couch_hash:md5_hash(lists:flatten([Source, term_to_binary(DDoc)])),
     BindFuns = bindings(State, Sig, {DDoc}),
     {Sig, makefun(State, Source, BindFuns)};
 makefun(_State, Source, BindFuns) when is_list(BindFuns) ->
diff --git a/src/couch/src/couch_stream.erl b/src/couch/src/couch_stream.erl
index 83b0611..0335629 100644
--- a/src/couch/src/couch_stream.erl
+++ b/src/couch/src/couch_stream.erl
@@ -98,9 +98,9 @@ foldl({Engine, EngineState}, Fun, Acc) ->
 foldl(Engine, <<>>, Fun, Acc) ->
     foldl(Engine, Fun, Acc);
 foldl(Engine, Md5, UserFun, UserAcc) ->
-    InitAcc = {crypto:hash_init(md5), UserFun, UserAcc},
+    InitAcc = {couch_hash:md5_hash_init(), UserFun, UserAcc},
     {Md5Acc, _, OutAcc} = foldl(Engine, fun foldl_md5/2, InitAcc),
-    Md5 = crypto:hash_final(Md5Acc),
+    Md5 = couch_hash:md5_hash_final(Md5Acc),
     OutAcc.
 
 
@@ -128,7 +128,7 @@ range_foldl(Engine, From, To, UserFun, UserAcc) when To >= From ->
 
 
 foldl_md5(Bin, {Md5Acc, UserFun, UserAcc}) ->
-    NewMd5Acc = crypto:hash_update(Md5Acc, Bin),
+    NewMd5Acc = couch_hash:md5_hash_update(Md5Acc, Bin),
     {NewMd5Acc, UserFun, UserFun(Bin, UserAcc)}.
 
 
@@ -201,8 +201,8 @@ init({Engine, OpenerPid, OpenerPriority, Options}) ->
     {ok, #stream{
             engine=Engine,
             opener_monitor=erlang:monitor(process, OpenerPid),
-            md5=crypto:hash_init(md5),
-            identity_md5=crypto:hash_init(md5),
+            md5=couch_hash:md5_hash_init(),
+            identity_md5=couch_hash:md5_hash_init(),
             encoding_fun=EncodingFun,
             end_encoding_fun=EndEncodingFun,
             max_buffer=couch_util:get_value(
@@ -227,7 +227,7 @@ handle_call({write, Bin}, _From, Stream) ->
         encoding_fun = EncodingFun} = Stream,
     if BinSize + BufferLen > Max ->
         WriteBin = lists:reverse(Buffer, [Bin]),
-        IdenMd5_2 = crypto:hash_update(IdenMd5, WriteBin),
+        IdenMd5_2 = couch_hash:md5_hash_update(IdenMd5, WriteBin),
         case EncodingFun(WriteBin) of
         [] ->
             % case where the encoder did some internal buffering
@@ -238,7 +238,7 @@ handle_call({write, Bin}, _From, Stream) ->
         WriteBin2 ->
             NewEngine = do_write(Engine, WriteBin2),
             WrittenLen2 = WrittenLen + iolist_size(WriteBin2),
-            Md5_2 = crypto:hash_update(Md5, WriteBin2)
+            Md5_2 = couch_hash:md5_hash_update(Md5, WriteBin2)
         end,
 
         {reply, ok, Stream#stream{
@@ -268,9 +268,9 @@ handle_call(close, _From, Stream) ->
         end_encoding_fun = EndEncodingFun} = Stream,
 
     WriteBin = lists:reverse(Buffer),
-    IdenMd5Final = crypto:hash_final(crypto:hash_update(IdenMd5, WriteBin)),
+    IdenMd5Final = couch_hash:md5_hash_final(couch_hash:md5_hash_update(IdenMd5, WriteBin)),
     WriteBin2 = EncodingFun(WriteBin) ++ EndEncodingFun(),
-    Md5Final = crypto:hash_final(crypto:hash_update(Md5, WriteBin2)),
+    Md5Final = couch_hash:md5_hash_final(couch_hash:md5_hash_update(Md5, WriteBin2)),
     Result = case WriteBin2 of
     [] ->
         {do_finalize(Engine), WrittenLen, IdenLen, Md5Final, IdenMd5Final};
diff --git a/src/couch/src/test_engine_util.erl b/src/couch/src/test_engine_util.erl
index fef9e9f..6cc6bcc 100644
--- a/src/couch/src/test_engine_util.erl
+++ b/src/couch/src/test_engine_util.erl
@@ -186,7 +186,7 @@ gen_write(Engine, St, {create, {DocId, Body, Atts0}}, UpdateSeq) ->
     [not_found] = Engine:open_docs(St, [DocId]),
     Atts = [couch_att:to_disk_term(Att) || Att <- Atts0],
 
-    Rev = crypto:hash(md5, term_to_binary({DocId, Body, Atts})),
+    Rev = couch_hash:md5_hash(term_to_binary({DocId, Body, Atts})),
 
     Doc0 = #doc{
         id = DocId,
@@ -323,11 +323,11 @@ gen_write(Engine, St, {Action, {DocId, Body, Atts0}}, UpdateSeq) ->
 
 
 gen_revision(conflict, DocId, _PrevRev, Body, Atts) ->
-    crypto:hash(md5, term_to_binary({DocId, Body, Atts}));
+    couch_hash:md5_hash(term_to_binary({DocId, Body, Atts}));
 gen_revision(delete, DocId, PrevRev, Body, Atts) ->
     gen_revision(update, DocId, PrevRev, Body, Atts);
 gen_revision(update, DocId, PrevRev, Body, Atts) ->
-    crypto:hash(md5, term_to_binary({DocId, PrevRev, Body, Atts})).
+    couch_hash:md5_hash(term_to_binary({DocId, PrevRev, Body, Atts})).
 
 
 gen_path(conflict, _RevPos, _PrevRevId, Rev, Leaf) ->
@@ -373,7 +373,7 @@ prep_atts(Engine, St, [{FileName, Data} | Rest]) ->
 
 write_att(Stream, FileName, OrigData, <<>>) ->
     {StreamEngine, Len, Len, Md5, Md5} = couch_stream:close(Stream),
-    couch_util:check_md5(Md5, crypto:hash(md5, OrigData)),
+    couch_util:check_md5(Md5, couch_hash:md5_hash(OrigData)),
     Len = size(OrigData),
     couch_att:new([
         {name, FileName},
diff --git a/src/couch/test/couchdb_attachments_tests.erl b/src/couch/test/couchdb_attachments_tests.erl
index a85a01f..04859db 100644
--- a/src/couch/test/couchdb_attachments_tests.erl
+++ b/src/couch/test/couchdb_attachments_tests.erl
@@ -208,7 +208,7 @@ should_upload_attachment_with_valid_md5_header({Host, DbName}) ->
         Headers = [
             {"Content-Length", "34"},
             {"Content-Type", "text/plain"},
-            {"Content-MD5", ?b2l(base64:encode(crypto:hash(md5, Body)))},
+            {"Content-MD5", ?b2l(base64:encode(couch_hash:md5_hash(Body)))},
             {"Host", Host}
         ],
         {ok, Code, Json} = request("PUT", AttUrl, Headers, Body),
@@ -224,7 +224,7 @@ should_upload_attachment_by_chunks_with_valid_md5_header({Host, DbName}) ->
         Body = [chunked_body([Part1, Part2]), "\r\n"],
         Headers = [
             {"Content-Type", "text/plain"},
-            {"Content-MD5", ?b2l(base64:encode(crypto:hash(md5, AttData)))},
+            {"Content-MD5", ?b2l(base64:encode(couch_hash:md5_hash(AttData)))},
             {"Host", Host},
             {"Transfer-Encoding", "chunked"}
         ],
@@ -239,7 +239,7 @@ should_upload_attachment_by_chunks_with_valid_md5_trailer({Host, DbName}) ->
         AttData = <<"We all live in a yellow submarine!">>,
         <<Part1:21/binary, Part2:13/binary>> = AttData,
         Body = [chunked_body([Part1, Part2]),
-                "Content-MD5: ", base64:encode(crypto:hash(md5, AttData)),
+                "Content-MD5: ", base64:encode(couch_hash:md5_hash(AttData)),
                 "\r\n\r\n"],
         Headers = [
             {"Content-Type", "text/plain"},
diff --git a/src/couch_epi/src/couch_epi_data.erl b/src/couch_epi/src/couch_epi_data.erl
index 93e39f6..bbed828 100644
--- a/src/couch_epi/src/couch_epi_data.erl
+++ b/src/couch_epi/src/couch_epi_data.erl
@@ -111,4 +111,4 @@ definitions({module, Modules}) ->
 
 hash_of_file(FilePath) ->
     {ok, Data} = file:read_file(FilePath),
-    crypto:hash(md5, Data).
+    couch_hash:md5_hash(Data).
diff --git a/src/couch_epi/src/couch_epi_util.erl b/src/couch_epi/src/couch_epi_util.erl
index e99db46..ea4b10e 100644
--- a/src/couch_epi/src/couch_epi_util.erl
+++ b/src/couch_epi/src/couch_epi_util.erl
@@ -22,7 +22,7 @@ module_version(Module) ->
     VSNs.
 
 hash(Term) ->
-    <<SigInt:128/integer>> = crypto:hash(md5, term_to_binary(Term)),
+    <<SigInt:128/integer>> = couch_hash:md5_hash(term_to_binary(Term)),
     lists:flatten(io_lib:format("\"~.36B\"",[SigInt])).
 
 module_exists(Module) ->
diff --git a/src/couch_index/test/couch_index_ddoc_updated_tests.erl b/src/couch_index/test/couch_index_ddoc_updated_tests.erl
index 40dadcc..0e23adf 100644
--- a/src/couch_index/test/couch_index_ddoc_updated_tests.erl
+++ b/src/couch_index/test/couch_index_ddoc_updated_tests.erl
@@ -118,7 +118,7 @@ fake_index() ->
         (idx_name, {_DbName, DDoc}) ->
             DDoc#doc.id;
         (signature, {_DbName, DDoc}) ->
-            crypto:hash(md5, term_to_binary(DDoc));
+            couch_hash:md5_hash(term_to_binary(DDoc));
         (update_seq, Seq) ->
             Seq
     end),
diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl
index 82bbd79..533dd2d 100644
--- a/src/couch_mrview/src/couch_mrview.erl
+++ b/src/couch_mrview/src/couch_mrview.erl
@@ -220,7 +220,7 @@ query_all_docs(Db, Args, Callback, Acc) when is_list(Args) ->
 query_all_docs(Db, Args0, Callback, Acc) ->
     Sig = couch_util:with_db(Db, fun(WDb) ->
         {ok, Info} = couch_db:get_db_info(WDb),
-        couch_index_util:hexsig(crypto:hash(md5, term_to_binary(Info)))
+        couch_index_util:hexsig(couch_hash:md5_hash(term_to_binary(Info)))
     end),
     Args1 = Args0#mrargs{view_type=map},
     Args2 = couch_mrview_util:validate_args(Args1),
diff --git a/src/couch_mrview/src/couch_mrview_util.erl b/src/couch_mrview/src/couch_mrview_util.erl
index eb461d0..120a9b8 100644
--- a/src/couch_mrview/src/couch_mrview_util.erl
+++ b/src/couch_mrview/src/couch_mrview_util.erl
@@ -157,7 +157,7 @@ ddoc_to_mrst(DbName, #doc{id=Id, body={Fields}}) ->
         keyseq_indexed=KeySeqIndexed
     },
     SigInfo = {Views, Language, DesignOpts, couch_index_util:sort_lib(Lib)},
-    {ok, IdxState#mrst{sig=crypto:hash(md5, term_to_binary(SigInfo))}}.
+    {ok, IdxState#mrst{sig=couch_hash:md5_hash(term_to_binary(SigInfo))}}.
 
 
 set_view_type(_Args, _ViewName, []) ->
@@ -203,7 +203,7 @@ view_sig(Db, State, View, #mrargs{include_docs=true}=Args) ->
         keyseq_indexed=KeySeqIndexed
     } = State,
     Term = view_sig_term(BaseSig, UpdateSeq, PurgeSeq, KeySeqIndexed, SeqIndexed),
-    couch_index_util:hexsig(crypto:hash(md5, term_to_binary(Term)));
+    couch_index_util:hexsig(couch_hash:md5_hash(term_to_binary(Term)));
 view_sig(Db, State, {_Nth, _Lang, View}, Args) ->
     view_sig(Db, State, View, Args);
 view_sig(_Db, State, View, Args0) ->
@@ -217,7 +217,7 @@ view_sig(_Db, State, View, Args0) ->
         extra=[]
     },
     Term = view_sig_term(Sig, UpdateSeq, PurgeSeq, KeySeqIndexed, SeqIndexed, Args),
-    couch_index_util:hexsig(crypto:hash(md5, term_to_binary(Term))).
+    couch_index_util:hexsig(couch_hash:md5_hash(term_to_binary(Term))).
 
 view_sig_term(BaseSig, UpdateSeq, PurgeSeq, false, false) ->
     {BaseSig, UpdateSeq, PurgeSeq};
@@ -1008,7 +1008,7 @@ sig_vsn_12x(State) ->
         {ViewInfo, State#mrst.language, State#mrst.design_opts,
             couch_index_util:sort_lib(State#mrst.lib)}
     end,
-    crypto:hash(md5, term_to_binary(SigData)).
+    couch_hash:md5_hash(term_to_binary(SigData)).
 
 old_view_format(View) ->
 {
diff --git a/src/couch_replicator/src/couch_replicator_ids.erl b/src/couch_replicator/src/couch_replicator_ids.erl
index e8faf8e..e10b980 100644
--- a/src/couch_replicator/src/couch_replicator_ids.erl
+++ b/src/couch_replicator/src/couch_replicator_ids.erl
@@ -112,7 +112,7 @@ maybe_append_filters(Base,
         {error, FilterParseError} ->
             throw({error, FilterParseError})
         end,
-    couch_util:to_hex(crypto:hash(md5, term_to_binary(Base2))).
+    couch_util:to_hex(couch_hash:md5_hash(term_to_binary(Base2))).
 
 
 maybe_append_options(Options, RepOptions) ->
diff --git a/src/couch_replicator/test/couch_replicator_many_leaves_tests.erl b/src/couch_replicator/test/couch_replicator_many_leaves_tests.erl
index b2445a2..eee5b16 100644
--- a/src/couch_replicator/test/couch_replicator_many_leaves_tests.erl
+++ b/src/couch_replicator/test/couch_replicator_many_leaves_tests.erl
@@ -141,7 +141,7 @@ add_doc_siblings(Db, _DocId, 0, AccDocs, AccRevs) ->
 
 add_doc_siblings(Db, DocId, NumLeaves, AccDocs, AccRevs) ->
     Value = ?l2b(?i2l(NumLeaves)),
-    Rev = crypto:hash(md5, Value),
+    Rev = couch_hash:md5_hash(Value),
     Doc = #doc{
         id = DocId,
         revs = {1, [Rev]},
diff --git a/src/couch_replicator/test/couch_replicator_test_helper.erl b/src/couch_replicator/test/couch_replicator_test_helper.erl
index 8ee2114..fd04091 100644
--- a/src/couch_replicator/test/couch_replicator_test_helper.erl
+++ b/src/couch_replicator/test/couch_replicator_test_helper.erl
@@ -93,16 +93,16 @@ find_att([Att | Rest], Name) ->
 att_md5(Att) ->
     Md50 = couch_att:foldl(
         Att,
-        fun(Chunk, Acc) -> crypto:hash_update(Acc, Chunk) end,
-        crypto:hash_init(md5)),
-    crypto:hash_final(Md50).
+        fun(Chunk, Acc) -> couch_hash:md5_hash_update(Acc, Chunk) end,
+        couch_hash:md5_hash_init()),
+    couch_hash:md5_hash_final(Md50).
 
 att_decoded_md5(Att) ->
     Md50 = couch_att:foldl_decode(
         Att,
-        fun(Chunk, Acc) -> crypto:hash_update(Acc, Chunk) end,
-        crypto:hash_init(md5)),
-    crypto:hash_final(Md50).
+        fun(Chunk, Acc) -> couch_hash:md5_hash_update(Acc, Chunk) end,
+        couch_hash:md5_hash_init()),
+    couch_hash:md5_hash_final(Md50).
 
 db_url(DbName) ->
     iolist_to_binary([
diff --git a/src/mem3/src/mem3_rep.erl b/src/mem3/src/mem3_rep.erl
index 3d91877..8d996d6 100644
--- a/src/mem3/src/mem3_rep.erl
+++ b/src/mem3/src/mem3_rep.erl
@@ -106,8 +106,8 @@ make_local_id(#shard{node=SourceNode}, #shard{node=TargetNode}, Filter) ->
 
 
 make_local_id(SourceThing, TargetThing, Filter) ->
-    S = couch_util:encodeBase64Url(crypto:hash(md5, term_to_binary(SourceThing))),
-    T = couch_util:encodeBase64Url(crypto:hash(md5, term_to_binary(TargetThing))),
+    S = couch_util:encodeBase64Url(couch_hash:md5_hash(term_to_binary(SourceThing))),
+    T = couch_util:encodeBase64Url(couch_hash:md5_hash(term_to_binary(TargetThing))),
     F = case is_function(Filter) of
         true ->
             {new_uniq, Hash} = erlang:fun_info(Filter, new_uniq),
@@ -339,7 +339,7 @@ update_locals(Acc) ->
 
 find_repl_doc(SrcDb, TgtUUIDPrefix) ->
     SrcUUID = couch_db:get_uuid(SrcDb),
-    S = couch_util:encodeBase64Url(crypto:hash(md5, term_to_binary(SrcUUID))),
+    S = couch_util:encodeBase64Url(couch_hash:md5_hash(term_to_binary(SrcUUID))),
     DocIdPrefix = <<"_local/shard-sync-", S/binary, "-">>,
     FoldFun = fun(#doc{id = DocId, body = {BodyProps}} = Doc, _) ->
         TgtUUID = couch_util:get_value(<<"target_uuid">>, BodyProps, <<>>),