diff --git a/apps/kds/src/kds_keyring.erl b/apps/kds/src/kds_keyring.erl index 9a3c69a..8332fb4 100644 --- a/apps/kds/src/kds_keyring.erl +++ b/apps/kds/src/kds_keyring.erl @@ -40,11 +40,19 @@ -define(KEY_BYTESIZE, 32). -define(FORMAT_VERSION, 1). +-define(DEFAULT_SEC_PARAMS, #{ + deduplication_hash_opts => #{ + n => 16384, + r => 8, + p => 1 + } +}). %% -spec new() -> keyring(). new() -> + SecurityParameters = application:get_env(kds, new_key_security_parameters, ?DEFAULT_SEC_PARAMS), #{ data => #{ keys => #{0 => kds_crypto:key()} @@ -54,7 +62,8 @@ new() -> version => 1, keys => #{ 0 => #{ - retired => false + retired => false, + security_parameters => SecurityParameters } } } @@ -63,6 +72,7 @@ new() -> -spec rotate(keyring()) -> keyring(). rotate(#{data := #{keys := Keys}, meta := #{current_key_id := CurrentKeyId, version := Version, keys := KeysMeta}}) -> MaxKeyId = lists:max(maps:keys(Keys)), + SecurityParameters = application:get_env(kds, new_key_security_parameters, ?DEFAULT_SEC_PARAMS), NewMaxKeyId = MaxKeyId + 1, #{ data => #{ @@ -71,7 +81,7 @@ rotate(#{data := #{keys := Keys}, meta := #{current_key_id := CurrentKeyId, vers meta => #{ current_key_id => CurrentKeyId, version => Version + 1, - keys => KeysMeta#{NewMaxKeyId => #{retired => false}} + keys => KeysMeta#{NewMaxKeyId => #{retired => false, security_parameters => SecurityParameters}} } }. diff --git a/apps/kds/src/kds_keyring_meta.erl b/apps/kds/src/kds_keyring_meta.erl index ec167fe..848135a 100644 --- a/apps/kds/src/kds_keyring_meta.erl +++ b/apps/kds/src/kds_keyring_meta.erl @@ -7,8 +7,10 @@ -export([update_meta/2]). -export([decode_keyring_meta_diff/1]). -export([decode_keyring_meta/1]). +-export([decode_security_parameters/1]). -export([encode_keyring_meta_diff/1]). -export([encode_keyring_meta/1]). +-export([encode_security_parameters/1]). -export_type([keyring_meta/0]). -export_type([keyring_meta_diff/0]). @@ -23,21 +25,33 @@ -type keyring_meta_diff() :: #{ current_key_id => non_neg_integer() | undefined, keys => #{ - key_id() => key_meta() + key_id() => key_meta_diff() } | undefined }. -type key_meta() :: #{ + retired := boolean(), + security_parameters := security_parameters() +}. +-type key_meta_diff() :: #{ retired := boolean() }. +-type security_parameters() :: #{ + deduplication_hash_opts := #{ + n := pos_integer(), + r := pos_integer(), + p := pos_integer() + } +}. -type key_id() :: kds_keyring:key_id(). -type encoded_keyring_meta() :: #'KeyringMeta'{}. -type encoded_keyring_meta_diff() :: #'KeyringMetaDiff'{}. +-type encoded_security_parameters() :: #'SecurityParameters'{}. -spec get_default_keyring_meta(kds_keyring:keyring_data()) -> keyring_meta(). get_default_keyring_meta(KeyringData) -> Keys = maps:get(keys, KeyringData), CurrentKeyId = lists:max(maps:keys(Keys)), - KeysMeta = maps:map(fun (_KeyId, _Key) -> #{retired => false} end, Keys), + KeysMeta = maps:map(fun(_KeyId, _Key) -> #{retired => false} end, Keys), #{current_key_id => CurrentKeyId, version => 1, keys => KeysMeta}. -spec update_meta(keyring_meta(), keyring_meta_diff()) -> keyring_meta(). @@ -73,7 +87,7 @@ decode_keyring_meta_diff(#'KeyringMetaDiff'{ current_key_id = CurrentKeyId, keys_meta = KeysMeta }) -> - DecodedKeysMeta = decode_keys_meta(KeysMeta), + DecodedKeysMeta = decode_keys_meta_diff(KeysMeta), #{current_key_id => CurrentKeyId, keys => DecodedKeysMeta}. -spec decode_keyring_meta(encoded_keyring_meta()) -> keyring_meta(). @@ -84,21 +98,44 @@ decode_keyring_meta(#'KeyringMeta'{ DecodedKeysMeta = decode_keys_meta(KeysMeta), #{current_key_id => CurrentKeyId, version => 1, keys => DecodedKeysMeta}. -decode_keys_meta(undefined) -> +decode_keys_meta_diff(undefined) -> undefined; -decode_keys_meta(KeysMeta) -> +decode_keys_meta_diff(KeysMetaDiff) -> maps:fold( - fun (K, #'KeyMeta'{retired = Retired}, Acc) -> + fun(K, #'KeyMetaDiff'{retired = Retired}, Acc) -> Acc#{K => #{retired => Retired}} end, #{}, + KeysMetaDiff). + +decode_keys_meta(KeysMeta) -> + maps:fold( + fun(K, + #'KeyMeta'{ + retired = Retired, + security_parameters = SecurityParameters + }, + Acc) -> + Acc#{K => #{ + retired => Retired, + security_parameters => decode_security_parameters(SecurityParameters) + }} + end, + #{}, KeysMeta). +-spec decode_security_parameters(encoded_security_parameters()) -> security_parameters(). +decode_security_parameters(#'SecurityParameters'{deduplication_hash_opts = HashOpts}) -> + #{deduplication_hash_opts => decode_scrypt_opts(HashOpts)}. + +decode_scrypt_opts(#'ScryptOptions'{n = N, r = R, p = P}) -> + #{n => N, r => R, p => P}. + -spec encode_keyring_meta_diff(keyring_meta_diff()) -> encoded_keyring_meta_diff(). encode_keyring_meta_diff(KeyringMetaDiff) -> #'KeyringMetaDiff'{ current_key_id = maps:get(current_key_id, KeyringMetaDiff, undefined), - keys_meta = encode_keys_meta(maps:get(keys, KeyringMetaDiff, undefined)) + keys_meta = encode_keys_meta_diff(maps:get(keys, KeyringMetaDiff, undefined)) }. -spec encode_keyring_meta(keyring_meta() | undefined) -> encoded_keyring_meta(). @@ -111,14 +148,39 @@ encode_keyring_meta(#{ EncodedKeysMeta = encode_keys_meta(KeysMeta), #'KeyringMeta'{current_key_id = CurrentKeyId, keys_meta = EncodedKeysMeta}. +encode_keys_meta_diff(undefined) -> + undefined; +encode_keys_meta_diff(KeysMetaDiff) -> + maps:fold( + fun(K, #{retired := Retired}, Acc) -> + Acc#{K => #'KeyMetaDiff'{retired = Retired}} + end, + #{}, + KeysMetaDiff + ). encode_keys_meta(undefined) -> undefined; encode_keys_meta(KeysMeta) -> maps:fold( - fun (K, #{retired := Retired}, Acc) -> - Acc#{K => #'KeyMeta'{retired = Retired}} + fun(K, + #{ + retired := Retired, + security_parameters := SecurityParameters + }, + Acc) -> + Acc#{K => #'KeyMeta'{ + retired = Retired, + security_parameters = encode_security_parameters(SecurityParameters) + }} end, #{}, KeysMeta - ). \ No newline at end of file + ). + +-spec encode_security_parameters(security_parameters()) -> encoded_security_parameters(). +encode_security_parameters(#{deduplication_hash_opts := ScryptOpts}) -> + #'SecurityParameters'{deduplication_hash_opts = encode_scrypt_opts(ScryptOpts)}. + +encode_scrypt_opts(#{n := N, r := R, p := P}) -> + #'ScryptOptions'{n = N, r = R, p = P}. diff --git a/apps/kds/src/kds_keyring_storage_file.erl b/apps/kds/src/kds_keyring_storage_file.erl index fb9c117..c10efb4 100644 --- a/apps/kds/src/kds_keyring_storage_file.erl +++ b/apps/kds/src/kds_keyring_storage_file.erl @@ -128,10 +128,28 @@ decode_encrypted_keyring(#{ decode_number_key_map(Map) -> maps:fold( - fun (K, #{<<"retired">> := Retired}, Acc) -> + fun (K, + #{ + <<"retired">> := Retired, + <<"security_parameters">> := #{ + <<"deduplication_hash_opts">> := #{ + <<"n">> := ScryptN, + <<"r">> := ScryptR, + <<"p">> := ScryptP + } + } + }, + Acc) -> Acc#{ binary_to_integer(K) => #{ - retired => Retired + retired => Retired, + security_parameters => #{ + deduplication_hash_opts => #{ + n => ScryptN, + r => ScryptR, + p => ScryptP + } + } } } end, diff --git a/apps/kds/src/kds_keyring_storage_thrift_handler.erl b/apps/kds/src/kds_keyring_storage_thrift_handler.erl index 00d164b..e30c500 100644 --- a/apps/kds/src/kds_keyring_storage_thrift_handler.erl +++ b/apps/kds/src/kds_keyring_storage_thrift_handler.erl @@ -47,11 +47,15 @@ encode_keyring(#{ encode_keys(Keys, KeysMeta) -> maps:fold( fun(K, V, Acc) -> - #{retired := Retired} = maps:get(K, KeysMeta), + #{ + retired := Retired, + security_parameters := SecurityParameters + } = maps:get(K, KeysMeta), Acc#{K => #'Key'{ data = V, meta = #'KeyMeta'{ - retired = Retired + retired = Retired, + security_parameters = kds_keyring_meta:encode_security_parameters(SecurityParameters) } }} end, diff --git a/apps/kds/test/kds_ct_utils.erl b/apps/kds/test/kds_ct_utils.erl index fe76342..374c37e 100644 --- a/apps/kds/test/kds_ct_utils.erl +++ b/apps/kds/test/kds_ct_utils.erl @@ -55,6 +55,13 @@ start_clear(Config) -> {fail_if_no_peer_cert, true} ] }}, + {new_key_security_parameters, #{ + deduplication_hash_opts => #{ + n => 16384, + r => 8, + p => 1 + } + }}, {protocol_opts, #{ request_timeout => 60000 }}, diff --git a/apps/kds/test/kds_keyring_client.erl b/apps/kds/test/kds_keyring_client.erl index eabcf7b..d8f7b9f 100644 --- a/apps/kds/test/kds_keyring_client.erl +++ b/apps/kds/test/kds_keyring_client.erl @@ -412,8 +412,16 @@ decode_keys(Keys) -> decode_keys_meta(Keys) -> maps:fold( - fun (K, #'Key'{meta = #'KeyMeta'{retired = Retired}}, Acc) -> - Acc#{K => #{retired => Retired}} + fun(K, + #'Key'{meta = #'KeyMeta'{ + retired = Retired, + security_parameters = SecurityParameters + }}, + Acc) -> + Acc#{K => #{ + retired => Retired, + security_parametes => kds_keyring_meta:decode_security_parameters(SecurityParameters) + }} end, #{}, Keys diff --git a/apps/kds/test/kds_keyring_meta_api_tests_SUITE.erl b/apps/kds/test/kds_keyring_meta_api_tests_SUITE.erl index 4afbfc1..d337d2a 100644 --- a/apps/kds/test/kds_keyring_meta_api_tests_SUITE.erl +++ b/apps/kds/test/kds_keyring_meta_api_tests_SUITE.erl @@ -91,14 +91,50 @@ init_check_meta(C) -> rotate_check_meta(C) -> _ = ?assertMatch( - #{keys := #{0 := #{retired := false}}}, + #{keys := #{ + 0 := #{ + retired := false, + security_parameters := #{ + deduplication_hash_opts := #{ + n := 16384, + r := 8, + p := 1 + } + } + } + }}, kds_keyring_client:get_keyring_meta(root_url(C)) ), + ok = application:set_env(kds, new_key_security_parameters, #{ + deduplication_hash_opts => #{ + n => 16384, + r => 7, + p => 1 + } + }), _ = kds_ct_keyring:rotate(C), _ = ?assertMatch( #{keys := #{ - 0 := #{retired := false}, - 1 := #{retired := false} + 0 := #{ + retired := false, + security_parameters := #{ + deduplication_hash_opts := #{ + n := 16384, + r := 8, + p := 1 + } + } + }, + 1 := #{ + retired := false, + security_parameters := #{ + deduplication_hash_opts := #{ + n := 16384, + r := 7, + p := 1 + } + } + } }}, kds_keyring_client:get_keyring_meta(root_url(C)) ). diff --git a/config/sys.config b/config/sys.config index a2253db..6ca2f8d 100644 --- a/config/sys.config +++ b/config/sys.config @@ -16,6 +16,13 @@ {protocol_opts, #{ request_timeout => 60000 }}, + {new_key_security_parameters, #{ + deduplication_hash_opts => #{ + n => 16384, + r => 8, + p => 1 + } + }}, {shutdown_timeout, 0}, {keyring_storage, kds_keyring_storage_file}, {keyring_storage_opts, #{ diff --git a/rebar.lock b/rebar.lock index 6c22525..a1cc120 100644 --- a/rebar.lock +++ b/rebar.lock @@ -4,7 +4,7 @@ {<<"cache">>,{pkg,<<"cache">>,<<"2.2.0">>},1}, {<<"cds_proto">>, {git,"git@github.com:rbkmoney/cds-proto.git", - {ref,"a8828869fcc3acbf382b8d4914665f5ef3c19a57"}}, + {ref,"f8a5e834b46a2cb261ff753132837df8e8681d1a"}}, 0}, {<<"certifi">>,{pkg,<<"certifi">>,<<"2.5.1">>},2}, {<<"cg_mon">>,