You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2015/09/25 13:03:55 UTC

couch commit: updated refs/heads/master to 9afa6a0

Repository: couchdb-couch
Updated Branches:
  refs/heads/master 8bbfba700 -> 9afa6a097


Fix crypto deprecations

COUCHDB-2825


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/9afa6a09
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/9afa6a09
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/9afa6a09

Branch: refs/heads/master
Commit: 9afa6a0979c37f4dfb72deb1c7d26aadd1aec694
Parents: 8bbfba7
Author: Robert Newson <rn...@apache.org>
Authored: Wed Sep 23 17:52:53 2015 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Fri Sep 25 11:58:33 2015 +0100

----------------------------------------------------------------------
 src/couch_crypto.erl               | 79 +++++++++++++++++++++++++++++++++
 src/couch_db.erl                   |  2 +-
 src/couch_db_updater.erl           |  2 +-
 src/couch_file.erl                 |  8 ++--
 src/couch_hotp.erl                 | 12 +----
 src/couch_httpd.erl                |  2 +-
 src/couch_httpd_auth.erl           |  6 +--
 src/couch_native_process.erl       |  4 +-
 src/couch_passwords.erl            |  8 ++--
 src/couch_server.erl               |  2 +-
 src/couch_stream.erl               | 28 ++++++------
 src/couch_util.erl                 | 18 --------
 test/couch_auth_cache_tests.erl    |  2 +-
 test/couchdb_attachments_tests.erl |  6 +--
 14 files changed, 115 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_crypto.erl
----------------------------------------------------------------------
diff --git a/src/couch_crypto.erl b/src/couch_crypto.erl
new file mode 100644
index 0000000..ccf9877
--- /dev/null
+++ b/src/couch_crypto.erl
@@ -0,0 +1,79 @@
+% 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_crypto).
+
+-export([hash/2, hash_init/1, hash_update/3, hash_final/2]).
+-export([hmac/3]).
+
+-compile([nowarn_deprecated_function]).
+
+hash(Alg, Data) ->
+    case {Alg, erlang:function_exported(crypto, hash, 2)} of
+        {_, true} ->
+            crypto:hash(Alg, Data);
+        {sha, false} ->
+            crypto:sha(Data);
+        {md5, false} ->
+            crypto:md5(Data);
+        {Alg, false} ->
+            throw({unsupported, Alg})
+    end.
+
+hash_init(Alg) ->
+    case {Alg, erlang:function_exported(crypto, hash_init, 1)} of
+        {_, true} ->
+            crypto:hash_init(Alg);
+        {sha, false} ->
+            crypto:sha_init();
+        {md5, false} ->
+            crypto:md5_init();
+        {Alg, false} ->
+            throw({unsupported, Alg})
+    end.
+
+
+hash_update(Alg, Context, Data) ->
+    case {Alg, erlang:function_exported(crypto, hash_update, 2)} of
+        {_, true} ->
+            crypto:hash_update(Context, Data);
+        {sha, false} ->
+            crypto:sha_update(Context, Data);
+        {md5, false} ->
+            crypto:md5_update(Context, Data);
+        {Alg, false} ->
+            throw({unsupported, Alg})
+    end.
+
+
+hash_final(Alg, Context) ->
+    case {Alg, erlang:function_exported(crypto, hash_final, 1)} of
+        {_, true} ->
+            crypto:hash_final(Context);
+        {sha, false} ->
+            crypto:sha_final(Context);
+        {md5, false} ->
+            crypto:md5_final(Context);
+        {Alg, false} ->
+            throw({unsupported, Alg})
+    end.
+
+
+hmac(Alg, Key, Data) ->
+    case {Alg, erlang:function_exported(crypto, hmac, 3)} of
+        {_, true} ->
+            crypto:hmac(Alg, Key, Data);
+        {sha, false} ->
+            crypto:sha_mac(Key, Data);
+        {Alg, false} ->
+            throw({unsupported, Alg})
+    end.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 6f767d9..4c0cd34 100644
--- a/src/couch_db.erl
+++ b/src/couch_db.erl
@@ -855,7 +855,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,
-            couch_util:md5(term_to_binary([Deleted, OldStart, OldRev, Body, Atts2]))
+            couch_crypto:hash(md5, term_to_binary([Deleted, OldStart, OldRev, Body, Atts2]))
     end.
 
 new_revs([], OutBuckets, IdRevsAcc) ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index 92139a9..2404984 100644
--- a/src/couch_db_updater.erl
+++ b/src/couch_db_updater.erl
@@ -1432,4 +1432,4 @@ make_doc_summary(#db{compression = Comp}, {Body0, Atts0}) ->
         couch_compress:compress(Atts0, Comp)
     end,
     SummaryBin = ?term_to_bin({Body, Atts}),
-    couch_file:assemble_file_chunk(SummaryBin, couch_util:md5(SummaryBin)).
+    couch_file:assemble_file_chunk(SummaryBin, couch_crypto:hash(md5, SummaryBin)).

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_file.erl
----------------------------------------------------------------------
diff --git a/src/couch_file.erl b/src/couch_file.erl
index 1a47d2b..e6cd01a 100644
--- a/src/couch_file.erl
+++ b/src/couch_file.erl
@@ -122,7 +122,7 @@ append_binary(Fd, Bin) ->
     
 append_binary_md5(Fd, Bin) ->
     ioq:call(Fd,
-        {append_bin, assemble_file_chunk(Bin, couch_util:md5(Bin))},
+        {append_bin, assemble_file_chunk(Bin, couch_crypto:hash(md5, Bin))},
         erlang:get(io_priority)).
 
 append_raw_chunk(Fd, Chunk) ->
@@ -165,7 +165,7 @@ pread_iolist(Fd, Pos) ->
     {ok, IoList, <<>>} ->
         {ok, IoList};
     {ok, IoList, Md5} ->
-        case couch_util:md5(IoList) of
+        case couch_crypto:hash(md5, IoList) of
         Md5 ->
             {ok, IoList};
         _ ->
@@ -279,7 +279,7 @@ read_header(Fd) ->
 
 write_header(Fd, Data) ->
     Bin = term_to_binary(Data),
-    Md5 = couch_util:md5(Bin),
+    Md5 = couch_crypto:hash(md5, 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)).
@@ -488,7 +488,7 @@ load_header(Fd, Block) ->
     end,
     <<Md5Sig:16/binary, HeaderBin/binary>> =
         iolist_to_binary(remove_block_prefixes(5, RawBin)),
-    Md5Sig = couch_util:md5(HeaderBin),
+    Md5Sig = couch_crypto:hash(md5, HeaderBin),
     {ok, HeaderBin}.
 
 maybe_read_more_iolist(Buffer, DataSize, _, _)

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_hotp.erl
----------------------------------------------------------------------
diff --git a/src/couch_hotp.erl b/src/couch_hotp.erl
index 896c52a..9d965be 100644
--- a/src/couch_hotp.erl
+++ b/src/couch_hotp.erl
@@ -16,7 +16,7 @@
 
 generate(Alg, Key, Counter, OutputLen)
   when is_atom(Alg), is_binary(Key), is_integer(Counter), is_integer(OutputLen) ->
-    Hmac = hmac(Alg, Key, <<Counter:64>>),
+    Hmac = couch_crypto:hmac(Alg, Key, <<Counter:64>>),
     Offset = binary:last(Hmac) band 16#f,
     Code =
         ((binary:at(Hmac, Offset) band 16#7f) bsl 24) +
@@ -28,13 +28,3 @@ generate(Alg, Key, Counter, OutputLen)
         7 -> Code rem 10000000;
         8 -> Code rem 100000000
     end.
-
-hmac(Alg, Key, Data) ->
-    case {Alg, erlang:function_exported(crypto, hmac, 3)} of
-        {_, true} ->
-            crypto:hmac(Alg, Key, Data);
-        {sha, false} ->
-            crypto:sha_mac(Key, Data);
-        {Alg, false} ->
-            throw({unsupported, Alg})
-    end.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd.erl b/src/couch_httpd.erl
index eeeb934..daa43d5 100644
--- a/src/couch_httpd.erl
+++ b/src/couch_httpd.erl
@@ -597,7 +597,7 @@ doc_etag(#doc{revs={Start, [DiskRev|_]}}) ->
     "\"" ++ ?b2l(couch_doc:rev_to_str({Start, DiskRev})) ++ "\"".
 
 make_etag(Term) ->
-    <<SigInt:128/integer>> = couch_util:md5(term_to_binary(Term)),
+    <<SigInt:128/integer>> = couch_crypto:hash(md5, term_to_binary(Term)),
     iolist_to_binary([$", io_lib:format("~.36B", [SigInt]), $"]).
 
 etag_match(Req, CurrentEtag) when is_binary(CurrentEtag) ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_httpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd_auth.erl b/src/couch_httpd_auth.erl
index 0035719..c305ad9 100644
--- a/src/couch_httpd_auth.erl
+++ b/src/couch_httpd_auth.erl
@@ -173,7 +173,7 @@ proxy_auth_user(Req) ->
                         undefined ->
                             Req#httpd{user_ctx=#user_ctx{name=?l2b(UserName), roles=Roles}};
                         Secret ->
-                            ExpectedToken = couch_util:to_hex(crypto:sha_mac(Secret, UserName)),
+                            ExpectedToken = couch_util:to_hex(couch_crypto:hmac(sha, Secret, UserName)),
                             case header_value(Req, XHeaderToken) of
                                 Token when Token == ExpectedToken ->
                                     Req#httpd{user_ctx=#user_ctx{name=?l2b(UserName),
@@ -217,7 +217,7 @@ cookie_authentication_handler(#httpd{mochi_req=MochiReq}=Req, AuthModule) ->
             {ok, UserProps, _AuthCtx} ->
                 UserSalt = couch_util:get_value(<<"salt">>, UserProps, <<"">>),
                 FullSecret = <<Secret/binary, UserSalt/binary>>,
-                ExpectedHash = crypto:sha_mac(FullSecret, User ++ ":" ++ TimeStr),
+                ExpectedHash = couch_crypto:hmac(sha, FullSecret, User ++ ":" ++ TimeStr),
                 Hash = ?l2b(HashStr),
                 Timeout = list_to_integer(
                     config:get("couch_httpd_auth", "timeout", "600")),
@@ -265,7 +265,7 @@ cookie_auth_header(_Req, _Headers) -> [].
 
 cookie_auth_cookie(Req, User, Secret, TimeStamp) ->
     SessionData = User ++ ":" ++ erlang:integer_to_list(TimeStamp, 16),
-    Hash = crypto:sha_mac(Secret, SessionData),
+    Hash = couch_crypto:hmac(sha, Secret, SessionData),
     mochiweb_cookies:cookie("AuthSession",
         couch_util:encodeBase64Url(SessionData ++ ":" ++ ?b2l(Hash)),
         [{path, "/"}] ++ cookie_scheme(Req) ++ max_age()).

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_native_process.erl
----------------------------------------------------------------------
diff --git a/src/couch_native_process.erl b/src/couch_native_process.erl
index 4cc862d..dcd01b3 100644
--- a/src/couch_native_process.erl
+++ b/src/couch_native_process.erl
@@ -325,11 +325,11 @@ bindings(State, Sig, DDoc) ->
 % thanks to erlview, via:
 % http://erlang.org/pipermail/erlang-questions/2003-November/010544.html
 makefun(State, Source) ->
-    Sig = couch_util:md5(Source),
+    Sig = couch_crypto:hash(md5, Source),
     BindFuns = bindings(State, Sig),
     {Sig, makefun(State, Source, BindFuns)}.
 makefun(State, Source, {DDoc}) ->
-    Sig = couch_util:md5(lists:flatten([Source, term_to_binary(DDoc)])),
+    Sig = couch_crypto:hash(md5, 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) ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_passwords.erl
----------------------------------------------------------------------
diff --git a/src/couch_passwords.erl b/src/couch_passwords.erl
index b06a584..1e7de15 100644
--- a/src/couch_passwords.erl
+++ b/src/couch_passwords.erl
@@ -23,7 +23,7 @@
 %% legacy scheme, not used for new passwords.
 -spec simple(binary(), binary()) -> binary().
 simple(Password, Salt) when is_binary(Password), is_binary(Salt) ->
-    ?l2b(couch_util:to_hex(crypto:sha(<<Password/binary, Salt/binary>>))).
+    ?l2b(couch_util:to_hex(couch_crypto:hash(sha, <<Password/binary, Salt/binary>>))).
 
 %% CouchDB utility functions
 -spec hash_admin_password(binary() | list()) -> binary().
@@ -36,7 +36,7 @@ hash_admin_password(ClearPassword) when is_binary(ClearPassword) ->
 
 hash_admin_password("simple", ClearPassword) -> % deprecated
     Salt = couch_uuids:random(),
-    Hash = crypto:sha(<<ClearPassword/binary, Salt/binary>>),
+    Hash = couch_crypto:hash(sha, <<ClearPassword/binary, Salt/binary>>),
     ?l2b("-hashed-" ++ couch_util:to_hex(Hash) ++ "," ++ ?b2l(Salt));
 hash_admin_password("pbkdf2", ClearPassword) ->
     Iterations = config:get("couch_httpd_auth", "iterations", "10000"),
@@ -98,12 +98,12 @@ pbkdf2(_Password, _Salt, Iterations, _BlockIndex, Iteration, _Prev, Acc)
     when Iteration > Iterations ->
     Acc;
 pbkdf2(Password, Salt, Iterations, BlockIndex, 1, _Prev, _Acc) ->
-    InitialBlock = crypto:sha_mac(Password,
+    InitialBlock = couch_crypto:hmac(sha, Password,
         <<Salt/binary,BlockIndex:32/integer>>),
     pbkdf2(Password, Salt, Iterations, BlockIndex, 2,
         InitialBlock, InitialBlock);
 pbkdf2(Password, Salt, Iterations, BlockIndex, Iteration, Prev, Acc) ->
-    Next = crypto:sha_mac(Password, Prev),
+    Next = couch_crypto:hmac(sha, Password, Prev),
     pbkdf2(Password, Salt, Iterations, BlockIndex, Iteration + 1,
                    Next, crypto:exor(Next, Acc)).
 

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_server.erl b/src/couch_server.erl
index fd468c5..3fea228 100644
--- a/src/couch_server.erl
+++ b/src/couch_server.erl
@@ -148,7 +148,7 @@ is_admin(User, ClearPwd) ->
     case config:get("admins", User) of
     "-hashed-" ++ HashedPwdAndSalt ->
         [HashedPwd, Salt] = string:tokens(HashedPwdAndSalt, ","),
-        couch_util:to_hex(crypto:sha(ClearPwd ++ Salt)) == HashedPwd;
+        couch_util:to_hex(couch_crypto:hash(sha, ClearPwd ++ Salt)) == HashedPwd;
     _Else ->
         false
     end.

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_stream.erl
----------------------------------------------------------------------
diff --git a/src/couch_stream.erl b/src/couch_stream.erl
index 6877f0f..1b51883 100644
--- a/src/couch_stream.erl
+++ b/src/couch_stream.erl
@@ -73,7 +73,7 @@ foldl(Fd, [Pos|Rest], Fun, Acc) ->
 foldl(Fd, PosList, <<>>, Fun, Acc) ->
     foldl(Fd, PosList, Fun, Acc);
 foldl(Fd, PosList, Md5, Fun, Acc) ->
-    foldl(Fd, PosList, Md5, couch_util:md5_init(), Fun, Acc).
+    foldl(Fd, PosList, Md5, couch_crypto:hash_init(md5), Fun, Acc).
 
 foldl_decode(Fd, PosList, Md5, Enc, Fun, Acc) ->
     {DecDataFun, DecEndFun} = case Enc of
@@ -83,25 +83,25 @@ foldl_decode(Fd, PosList, Md5, Enc, Fun, Acc) ->
         identity_enc_dec_funs()
     end,
     Result = foldl_decode(
-        DecDataFun, Fd, PosList, Md5, couch_util:md5_init(), Fun, Acc
+        DecDataFun, Fd, PosList, Md5, couch_crypto:hash_init(md5), Fun, Acc
     ),
     DecEndFun(),
     Result.
 
 foldl(_Fd, [], Md5, Md5Acc, _Fun, Acc) ->
-    Md5 = couch_util:md5_final(Md5Acc),
+    Md5 = couch_crypto:hash_final(md5, Md5Acc),
     Acc;
 foldl(Fd, [{Pos, _Size}], Md5, Md5Acc, Fun, Acc) -> % 0110 UPGRADE CODE
     foldl(Fd, [Pos], Md5, Md5Acc, Fun, Acc);
 foldl(Fd, [Pos], Md5, Md5Acc, Fun, Acc) ->
     {ok, Bin} = couch_file:pread_iolist(Fd, Pos),
-    Md5 = couch_util:md5_final(couch_util:md5_update(Md5Acc, Bin)),
+    Md5 = couch_crypto:hash_final(md5, couch_crypto:hash_update(md5, Md5Acc, Bin)),
     Fun(Bin, Acc);
 foldl(Fd, [{Pos, _Size}|Rest], Md5, Md5Acc, Fun, Acc) ->
     foldl(Fd, [Pos|Rest], Md5, Md5Acc, Fun, Acc);
 foldl(Fd, [Pos|Rest], Md5, Md5Acc, Fun, Acc) ->
     {ok, Bin} = couch_file:pread_iolist(Fd, Pos),
-    foldl(Fd, Rest, Md5, couch_util:md5_update(Md5Acc, Bin), Fun, Fun(Bin, Acc)).
+    foldl(Fd, Rest, Md5, couch_crypto:hash_update(md5, Md5Acc, Bin), Fun, Fun(Bin, Acc)).
 
 range_foldl(Fd, PosList, From, To, Fun, Acc) ->
     range_foldl(Fd, PosList, From, To, 0, Fun, Acc).
@@ -134,13 +134,13 @@ clip(Value, Lo, Hi) ->
     end.
 
 foldl_decode(_DecFun, _Fd, [], Md5, Md5Acc, _Fun, Acc) ->
-    Md5 = couch_util:md5_final(Md5Acc),
+    Md5 = couch_crypto:hash_final(md5, Md5Acc),
     Acc;
 foldl_decode(DecFun, Fd, [{Pos, _Size}], Md5, Md5Acc, Fun, Acc) ->
     foldl_decode(DecFun, Fd, [Pos], Md5, Md5Acc, Fun, Acc);
 foldl_decode(DecFun, Fd, [Pos], Md5, Md5Acc, Fun, Acc) ->
     {ok, EncBin} = couch_file:pread_iolist(Fd, Pos),
-    Md5 = couch_util:md5_final(couch_util:md5_update(Md5Acc, EncBin)),
+    Md5 = couch_crypto:hash_final(md5, couch_crypto:hash_update(md5, Md5Acc, EncBin)),
     Bin = DecFun(EncBin),
     Fun(Bin, Acc);
 foldl_decode(DecFun, Fd, [{Pos, _Size}|Rest], Md5, Md5Acc, Fun, Acc) ->
@@ -148,7 +148,7 @@ foldl_decode(DecFun, Fd, [{Pos, _Size}|Rest], Md5, Md5Acc, Fun, Acc) ->
 foldl_decode(DecFun, Fd, [Pos|Rest], Md5, Md5Acc, Fun, Acc) ->
     {ok, EncBin} = couch_file:pread_iolist(Fd, Pos),
     Bin = DecFun(EncBin),
-    Md5Acc2 = couch_util:md5_update(Md5Acc, EncBin),
+    Md5Acc2 = couch_crypto:hash_update(md5, Md5Acc, EncBin),
     foldl_decode(DecFun, Fd, Rest, Md5, Md5Acc2, Fun, Fun(Bin, Acc)).
 
 gzip_init(Options) ->
@@ -209,8 +209,8 @@ init({Fd, OpenerPid, Options}) ->
     {ok, #stream{
             fd=Fd,
             opener_monitor=erlang:monitor(process, OpenerPid),
-            md5=couch_util:md5_init(),
-            identity_md5=couch_util:md5_init(),
+            md5=couch_crypto:hash_init(md5),
+            identity_md5=couch_crypto:hash_init(md5),
             encoding_fun=EncodingFun,
             end_encoding_fun=EndEncodingFun,
             max_buffer=couch_util:get_value(
@@ -236,7 +236,7 @@ handle_call({write, Bin}, _From, Stream) ->
         encoding_fun = EncodingFun} = Stream,
     if BinSize + BufferLen > Max ->
         WriteBin = lists:reverse(Buffer, [Bin]),
-        IdenMd5_2 = couch_util:md5_update(IdenMd5, WriteBin),
+        IdenMd5_2 = couch_crypto:hash_update(md5, IdenMd5, WriteBin),
         case EncodingFun(WriteBin) of
         [] ->
             % case where the encoder did some internal buffering
@@ -247,7 +247,7 @@ handle_call({write, Bin}, _From, Stream) ->
         WriteBin2 ->
             {ok, Pos, _} = couch_file:append_binary(Fd, WriteBin2),
             WrittenLen2 = WrittenLen + iolist_size(WriteBin2),
-            Md5_2 = couch_util:md5_update(Md5, WriteBin2),
+            Md5_2 = couch_crypto:hash_update(md5, Md5, WriteBin2),
             Written2 = [{Pos, iolist_size(WriteBin2)}|Written]
         end,
 
@@ -279,9 +279,9 @@ handle_call(close, _From, Stream) ->
         end_encoding_fun = EndEncodingFun} = Stream,
 
     WriteBin = lists:reverse(Buffer),
-    IdenMd5Final = couch_util:md5_final(couch_util:md5_update(IdenMd5, WriteBin)),
+    IdenMd5Final = couch_crypto:hash_final(md5, couch_crypto:hash_update(md5, IdenMd5, WriteBin)),
     WriteBin2 = EncodingFun(WriteBin) ++ EndEncodingFun(),
-    Md5Final = couch_util:md5_final(couch_util:md5_update(Md5, WriteBin2)),
+    Md5Final = couch_crypto:hash_final(md5, couch_crypto:hash_update(md5, Md5, WriteBin2)),
     Result = case WriteBin2 of
     [] ->
         {lists:reverse(Written), WrittenLen, IdenLen, Md5Final, IdenMd5Final};

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/src/couch_util.erl
----------------------------------------------------------------------
diff --git a/src/couch_util.erl b/src/couch_util.erl
index 2015244..9593451 100644
--- a/src/couch_util.erl
+++ b/src/couch_util.erl
@@ -24,7 +24,6 @@
 -export([json_encode/1, json_decode/1]).
 -export([verify/2,simple_call/2,shutdown_sync/1]).
 -export([get_value/2, get_value/3]).
--export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
 -export([reorder_results/2]).
 -export([url_strip_password/1]).
 -export([encode_doc_id/1]).
@@ -417,23 +416,6 @@ verify(X, Y) when is_list(X) and is_list(Y) ->
     end;
 verify(_X, _Y) -> false.
 
--spec md5(Data::(iolist() | binary())) -> Digest::binary().
-md5(Data) ->
-    try crypto:md5(Data) catch error:_ -> erlang:md5(Data) end.
-
--spec md5_init() -> Context::binary().
-md5_init() ->
-    try crypto:md5_init() catch error:_ -> erlang:md5_init() end.
-
--spec md5_update(Context::binary(), Data::(iolist() | binary())) ->
-    NewContext::binary().
-md5_update(Ctx, D) ->
-    try crypto:md5_update(Ctx,D) catch error:_ -> erlang:md5_update(Ctx,D) end.
-
--spec md5_final(Context::binary()) -> Digest::binary().
-md5_final(Ctx) ->
-    try crypto:md5_final(Ctx) catch error:_ -> erlang:md5_final(Ctx) end.
-
 % linear search is faster for small lists, length() is 0.5 ms for 100k list
 reorder_results(Keys, SortedResults) when length(Keys) < 100 ->
     [couch_util:get_value(Key, SortedResults) || Key <- Keys];

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/test/couch_auth_cache_tests.erl
----------------------------------------------------------------------
diff --git a/test/couch_auth_cache_tests.erl b/test/couch_auth_cache_tests.erl
index cba77ed..bf89a88 100644
--- a/test/couch_auth_cache_tests.erl
+++ b/test/couch_auth_cache_tests.erl
@@ -185,7 +185,7 @@ update_user_doc(DbName, UserName, Password, Rev) ->
     {ok, couch_doc:rev_to_str(NewRev)}.
 
 hash_password(Password) ->
-    ?l2b(couch_util:to_hex(crypto:sha(iolist_to_binary([Password, ?SALT])))).
+    ?l2b(couch_util:to_hex(couch_crypto:hash(sha, iolist_to_binary([Password, ?SALT])))).
 
 shutdown_db(DbName) ->
     {ok, AuthDb} = couch_db:open_int(DbName, [?ADMIN_CTX]),

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/9afa6a09/test/couchdb_attachments_tests.erl
----------------------------------------------------------------------
diff --git a/test/couchdb_attachments_tests.erl b/test/couchdb_attachments_tests.erl
index 4822987..11493a8 100644
--- a/test/couchdb_attachments_tests.erl
+++ b/test/couchdb_attachments_tests.erl
@@ -207,7 +207,7 @@ should_upload_attachment_with_valid_md5_header({Host, DbName}) ->
         Headers = [
             {"Content-Length", "34"},
             {"Content-Type", "text/plain"},
-            {"Content-MD5", ?b2l(base64:encode(couch_util:md5(Body)))},
+            {"Content-MD5", ?b2l(base64:encode(couch_crypto:hash(md5, Body)))},
             {"Host", Host}
         ],
         {ok, Code, Json} = request("PUT", AttUrl, Headers, Body),
@@ -223,7 +223,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(couch_util:md5(AttData)))},
+            {"Content-MD5", ?b2l(base64:encode(couch_crypto:hash(md5, AttData)))},
             {"Host", Host},
             {"Transfer-Encoding", "chunked"}
         ],
@@ -238,7 +238,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(couch_util:md5(AttData)),
+                "Content-MD5: ", base64:encode(couch_crypto:hash(md5, AttData)),
                 "\r\n\r\n"],
         Headers = [
             {"Content-Type", "text/plain"},