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 2022/05/06 21:16:29 UTC
[couchdb] branch aegis_3.x updated: performance boost and also hides the key from inspection
This is an automated email from the ASF dual-hosted git repository.
rnewson pushed a commit to branch aegis_3.x
in repository https://gitbox.apache.org/repos/asf/couchdb.git
The following commit(s) were added to refs/heads/aegis_3.x by this push:
new 0320343e1 performance boost and also hides the key from inspection
0320343e1 is described below
commit 0320343e1a71d9e419c08b1c0c175d1e6aae2c0f
Author: Robert Newson <rn...@apache.org>
AuthorDate: Fri May 6 22:16:18 2022 +0100
performance boost and also hides the key from inspection
---
src/couch/src/couch_file.erl | 48 +++++++++++++++++++++++++-------------------
1 file changed, 27 insertions(+), 21 deletions(-)
diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl
index f52a12f9e..f64c36ef2 100644
--- a/src/couch/src/couch_file.erl
+++ b/src/couch/src/couch_file.erl
@@ -35,7 +35,8 @@
eof = 0,
db_monitor,
pread_limit = 0,
- key
+ enc,
+ dec
}).
% public API
@@ -455,7 +456,7 @@ init({Filepath, Options, ReturnPid, Ref}) ->
ok = file:sync(Fd),
maybe_track_open_os_files(Options),
erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
- init_key(#file{fd = Fd, is_sys = IsSys, pread_limit = Limit});
+ init_crypto(#file{fd = Fd, is_sys = IsSys, pread_limit = Limit});
false ->
ok = file:close(Fd),
init_status_error(ReturnPid, Ref, {error, eexist})
@@ -463,7 +464,7 @@ init({Filepath, Options, ReturnPid, Ref}) ->
false ->
maybe_track_open_os_files(Options),
erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
- init_key(#file{fd = Fd, is_sys = IsSys, pread_limit = Limit})
+ init_crypto(#file{fd = Fd, is_sys = IsSys, pread_limit = Limit})
end;
Error ->
init_status_error(ReturnPid, Ref, Error)
@@ -480,7 +481,7 @@ init({Filepath, Options, ReturnPid, Ref}) ->
maybe_track_open_os_files(Options),
{ok, Eof} = file:position(Fd, eof),
erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
- init_key(#file{fd = Fd, eof = Eof, is_sys = IsSys, pread_limit = Limit});
+ init_crypto(#file{fd = Fd, eof = Eof, is_sys = IsSys, pread_limit = Limit});
Error ->
init_status_error(ReturnPid, Ref, Error)
end;
@@ -583,7 +584,7 @@ handle_call({truncate, Pos}, _From, #file{fd = Fd} = File) ->
{ok, Pos} = file:position(Fd, Pos),
case file:truncate(Fd) of
ok ->
- case init_key(File#file{eof = Pos}) of
+ case init_crypto(File#file{eof = Pos}) of
{ok, File1} ->
{reply, ok, File1};
{error, Reason} ->
@@ -928,47 +929,52 @@ reset_eof(#file{} = File) ->
%% we've wiped all the data, including the wrapped key, so we need a new one.
-init_key(#file{eof = 0} = File) ->
+init_crypto(#file{eof = 0} = File) ->
Key = crypto:strong_rand_bytes(32),
WrappedKey = couch_keywrap:key_wrap(master_key(), Key),
Header = <<?ENCRYPTED_HEADER, WrappedKey/binary>>,
ok = file:write(File#file.fd, Header),
ok = file:sync(File#file.fd),
- {ok, File#file{eof = iolist_size(Header), key = Key}};
+ {ok, init_crypto(File#file{eof = iolist_size(Header)}, Key)};
%% we're opening an existing file and need to unwrap the key.
-init_key(#file{key = undefined} = File) ->
+init_crypto(#file{enc = undefined, dec = undefined} = File) ->
case file:pread(File#file.fd, 0, 48) of
{ok, <<?ENCRYPTED_HEADER, WrappedKey/binary>>} ->
case couch_keywrap:key_unwrap(master_key(), WrappedKey) of
fail ->
{error, unwrap_failed};
Key when is_binary(Key) ->
- {ok, File#file{key = Key}}
+ {ok, init_crypto(File, Key)}
end;
{ok, _} ->
- {ok, File#file{key = unencrypted}};
+ {ok, File#file{enc = unencrypted, dec = unencrypted}};
Else ->
Else
end;
%% we're opening an existing file that contains a wrapped key
%% which we've already unwrapped.
-init_key(#file{eof = Eof, key = Key} = File) when Eof > 48, is_binary(Key) ->
+init_crypto(#file{eof = Eof, enc = Enc, dec = Dec} = File) when Eof > 48, Enc /= undefined, Dec /= undefined ->
{ok, File}.
+init_crypto(#file{} = File, Key) ->
+ EncState = crypto:crypto_dyn_iv_init(aes_256_ctr, Key, true),
+ DecState = crypto:crypto_dyn_iv_init(aes_256_ctr, Key, false),
+ File#file{enc = EncState, dec = DecState}.
+
%% We can encrypt any section of the file but we must make
%% sure we align with the key stream.
-encrypted_write(#file{key = unencrypted} = File, Data) ->
+encrypted_write(#file{enc = unencrypted} = File, Data) ->
file:write(File#file.fd, Data);
encrypted_write(#file{} = File, Data) ->
- CipherText = encrypt(File#file.key, File#file.eof, pad(File#file.eof, Data)),
+ CipherText = encrypt(File#file.enc, File#file.eof, pad(File#file.eof, Data)),
file:write(File#file.fd, unpad(File#file.eof, CipherText)).
-encrypted_pread(#file{key = unencrypted} = File, LocNums) ->
+encrypted_pread(#file{dec = unencrypted} = File, LocNums) ->
file:pread(File#file.fd, LocNums);
encrypted_pread(#file{} = File, LocNums) ->
@@ -976,7 +982,7 @@ encrypted_pread(#file{} = File, LocNums) ->
{ok, DataL} ->
{ok, lists:zipwith(
fun({Pos, _Len}, CipherText) ->
- PlainText = decrypt(File#file.key, Pos, pad(Pos, CipherText)),
+ PlainText = decrypt(File#file.dec, Pos, pad(Pos, CipherText)),
unpad(Pos, PlainText) end,
LocNums,
DataL)};
@@ -985,27 +991,27 @@ encrypted_pread(#file{} = File, LocNums) ->
end.
-encrypted_pread(#file{key = unencrypted} = File, Pos, Len) ->
+encrypted_pread(#file{dec = unencrypted} = File, Pos, Len) ->
file:pread(File#file.fd, Pos, Len);
encrypted_pread(#file{} = File, Pos, Len) ->
case file:pread(File#file.fd, Pos, Len) of
{ok, CipherText} ->
- PlainText = decrypt(File#file.key, Pos, pad(Pos, CipherText)),
+ PlainText = decrypt(File#file.dec, Pos, pad(Pos, CipherText)),
{ok, unpad(Pos, PlainText)};
Else ->
Else
end.
-encrypt(Key, Pos, Data) ->
+encrypt(Enc, Pos, Data) ->
IV = aes_ctr_iv(Pos),
- crypto:crypto_one_time(aes_256_ctr, Key, IV, Data, true).
+ crypto:crypto_dyn_iv_update(Enc, Data, IV).
-decrypt(Key, Pos, Data) ->
+decrypt(Dec, Pos, Data) ->
IV = aes_ctr_iv(Pos),
- crypto:crypto_one_time(aes_256_ctr, Key, IV, Data, false).
+ crypto:crypto_dyn_iv_update(Dec, Data, IV).
aes_ctr_iv(Pos) ->