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 382774726 Add key rotation facility
382774726 is described below
commit 3827747268f54f209f5c515428df2393e91e23a7
Author: Robert Newson <[email protected]>
AuthorDate: Tue May 10 08:29:45 2022 +0100
Add key rotation facility
---
rel/overlay/etc/default.ini | 9 +++++++--
src/couch/src/couch_file.erl | 37 +++++++++++++++++--------------------
2 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index 98349f5eb..9777d072a 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -6,8 +6,6 @@ name = {{package_author_name}}
uuid = {{uuid}}
database_dir = {{data_dir}}
view_index_dir = {{view_index_dir}}
-encryption_password = super_secret_password
-encryption_salt = no_saltier_than_this
; util_driver_dir =
; plugin_dir =
;os_process_timeout = 5000 ; 5 seconds. for view servers.
@@ -749,3 +747,10 @@ port = {{prometheus_port}}
; to disable this setting could be if the views need an upgrade but located on
; read-only file system.
;commit_on_header_upgrade = true
+
+[encryption]
+master_key_id = bec46c7438e685d6
+
+[encryption_keys]
+254abda45788029b = 0585d781ef090ee26f329a36f66935ce
+bec46c7438e685d6 = e6f598615eb7502b473b101d64f56410
\ No newline at end of file
diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl
index 6198d8f9a..f9579b301 100644
--- a/src/couch/src/couch_file.erl
+++ b/src/couch/src/couch_file.erl
@@ -931,17 +931,18 @@ reset_eof(#file{} = File) ->
%% we've wiped all the data, including the wrapped key, so we need a new one.
init_crypto(#file{eof = 0} = File) ->
Key = crypto:strong_rand_bytes(32),
- WrappedKey = aegis:wrap_key(master_key(), [], Key),
- Header = <<?ENCRYPTED_HEADER, WrappedKey/binary>>,
+ {MasterKeyId, MasterKey} = current_master_key(),
+ WrappedKey = aegis:wrap_key(MasterKey, [MasterKeyId], Key),
+ Header = <<?ENCRYPTED_HEADER, MasterKeyId:16/binary, WrappedKey/binary>>,
ok = file:write(File#file.fd, Header),
ok = file:sync(File#file.fd),
{ok, init_crypto(File#file{eof = iolist_size(Header)}, Key)};
%% we're opening an existing file and need to unwrap the key.
init_crypto(#file{enc = undefined, dec = undefined} = File) ->
- case file:pread(File#file.fd, 0, 64) of
- {ok, <<?ENCRYPTED_HEADER, WrappedKey:48/binary>>} ->
- case aegis:unwrap_key(master_key(), [], WrappedKey) of
+ case file:pread(File#file.fd, 0, 80) of
+ {ok, <<?ENCRYPTED_HEADER, MasterKeyId:16/binary,
WrappedKey:48/binary>>} ->
+ case aegis:unwrap_key(master_key(MasterKeyId), [MasterKeyId],
WrappedKey) of
fail ->
{error, unwrap_failed};
Key when is_binary(Key) ->
@@ -1027,27 +1028,23 @@ unpad(Pos, Bin) when is_binary(Bin) ->
Result.
-master_key() ->
- couch_pbkdf2:pbkdf2(sha256, master_password(), master_salt(), 100000).
+current_master_key() ->
+ KeyId = config:get("encryption", "master_key_id"),
+ {?l2b(KeyId), master_key(KeyId)}.
-master_password() ->
- case config:get("couchdb", "encryption_password") of
- undefined ->
- undefined;
- Password ->
- ?l2b(Password)
- end.
+master_key(KeyId) ->
+ get_config_binary("encryption_keys", couch_util:to_list(KeyId), undefined).
-master_salt() ->
- case config:get("couchdb", "encryption_salt") of
+
+get_config_binary(Section, Key, Default) ->
+ case config:get(Section, Key) of
undefined ->
- undefined;
- Salt ->
- ?l2b(Salt)
+ Default;
+ Value ->
+ ?l2b(Value)
end.
-
-ifdef(TEST).
-include_lib("couch/include/couch_eunit.hrl").