mirror of
https://github.com/valitydev/kds.git
synced 2024-11-06 00:05:18 +00:00
CDS-94: Fix old keyring compatibility (#9)
* CDS-94: Fix old keyring compatibility * CDS-94: Hide error from logs
This commit is contained in:
parent
bbbf99db96
commit
c022cceb1c
@ -58,8 +58,8 @@ encrypt(Key, Plain) ->
|
||||
try
|
||||
{Cipher, Tag} = crypto:block_encrypt(?CIPHER_TYPE, Key, IV, {AAD, Plain}),
|
||||
marshall_cedf(#cedf{iv = IV, aad = AAD, cipher = Cipher, tag = Tag})
|
||||
catch Class:Reason ->
|
||||
_ = logger:error("encryption failed with ~p ~p", [Class, Reason]),
|
||||
catch Class:_Reason:Stacktrace ->
|
||||
_ = logger:error("encryption failed with ~p ST: ~p", [Class, Stacktrace]),
|
||||
throw(encryption_failed)
|
||||
end.
|
||||
|
||||
@ -88,8 +88,8 @@ decrypt(Key, MarshalledCEDF) ->
|
||||
throw(decryption_failed);
|
||||
Plain ->
|
||||
Plain
|
||||
catch Type:Error ->
|
||||
_ = logger:error("decryption failed with ~p ~p", [Type, Error]),
|
||||
catch Type:_Error:Stacktrace ->
|
||||
_ = logger:error("decryption failed with ~p ST: ~p", [Type, Stacktrace]),
|
||||
throw(decryption_failed)
|
||||
end.
|
||||
|
||||
|
@ -114,20 +114,26 @@ encrypt(MasterKey, #{data := KeyringData, meta := KeyringMeta}) ->
|
||||
|
||||
-spec decrypt(key(), encrypted_keyring()) -> {ok, keyring()} | {error, decryption_failed}.
|
||||
decrypt(MasterKey, #{data := EncryptedKeyringData, meta := KeyringMeta}) ->
|
||||
try unmarshall(kds_crypto:decrypt(MasterKey, base64:decode(EncryptedKeyringData))) of
|
||||
KeyringData ->
|
||||
case KeyringMeta of
|
||||
undefined ->
|
||||
case KeyringMeta of
|
||||
undefined ->
|
||||
try unmarshall(kds_crypto:decrypt(MasterKey, EncryptedKeyringData)) of
|
||||
KeyringData ->
|
||||
{ok, #{
|
||||
data => KeyringData,
|
||||
meta => kds_keyring_meta:get_default_keyring_meta(KeyringData)
|
||||
}};
|
||||
_ ->
|
||||
}}
|
||||
catch
|
||||
decryption_failed ->
|
||||
{error, decryption_failed}
|
||||
end;
|
||||
_ ->
|
||||
try unmarshall(kds_crypto:decrypt(MasterKey, base64:decode(EncryptedKeyringData))) of
|
||||
KeyringData ->
|
||||
{ok, #{data => KeyringData, meta => KeyringMeta}}
|
||||
catch
|
||||
decryption_failed ->
|
||||
{error, decryption_failed}
|
||||
end
|
||||
catch
|
||||
decryption_failed ->
|
||||
{error, decryption_failed}
|
||||
end.
|
||||
|
||||
-spec marshall(keyring_data()) -> binary().
|
||||
@ -140,7 +146,7 @@ marshall(#{keys := Keys}) ->
|
||||
-spec unmarshall(binary()) -> keyring_data().
|
||||
unmarshall(<<MaxKeyId, Keys/binary>> = MarshalledKeyring) ->
|
||||
KeysSize = erlang:byte_size(Keys),
|
||||
case (KeysSize div 33 =:= MaxKeyId) and (KeysSize rem 33 =:= 0) of
|
||||
case (KeysSize div 33 =:= (MaxKeyId + 1)) and (KeysSize rem 33 =:= 0) of
|
||||
true ->
|
||||
#{keys => unmarshall_keys(Keys, #{})};
|
||||
false ->
|
||||
|
@ -47,11 +47,23 @@
|
||||
-type encoded_keyring_meta_diff() :: #'cds_KeyringMetaDiff'{}.
|
||||
-type encoded_security_parameters() :: #'cds_SecurityParameters'{}.
|
||||
|
||||
-define(DEFAULT_SEC_PARAMS, #{
|
||||
deduplication_hash_opts => #{
|
||||
n => 16384,
|
||||
r => 8,
|
||||
p => 1
|
||||
}
|
||||
}).
|
||||
-define(DEFAULT_KEY_META, #{
|
||||
retired => false,
|
||||
security_parameters => application:get_env(kds, new_key_security_parameters, ?DEFAULT_SEC_PARAMS)
|
||||
}).
|
||||
|
||||
-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) -> ?DEFAULT_KEY_META end, Keys),
|
||||
#{current_key_id => CurrentKeyId, version => 1, keys => KeysMeta}.
|
||||
|
||||
-spec update_meta(keyring_meta(), keyring_meta_diff()) -> keyring_meta().
|
||||
|
@ -1,5 +1,7 @@
|
||||
-module(kds_ct_keyring).
|
||||
|
||||
-include_lib("shamir/include/shamir.hrl").
|
||||
|
||||
-export([init/1]).
|
||||
-export([rekey/1]).
|
||||
-export([lock/1]).
|
||||
@ -7,9 +9,12 @@
|
||||
-export([rotate/1]).
|
||||
|
||||
-export([decrypt_and_sign_masterkeys/3]).
|
||||
-export([decrypt_and_reconstruct/3]).
|
||||
-export([validate_init/2]).
|
||||
-export([validate_rekey/2]).
|
||||
|
||||
-export([marshall_old_format/1]).
|
||||
|
||||
%%
|
||||
%% Internal types
|
||||
%%
|
||||
@ -41,6 +46,29 @@ decrypt_and_sign_masterkeys(EncryptedMasterKeyShares, EncPrivateKeys, SigPrivate
|
||||
end,
|
||||
EncryptedMasterKeyShares).
|
||||
|
||||
-spec decrypt_and_reconstruct(kds_keysharing:encrypted_master_key_shares(), map(), integer()) ->
|
||||
kds_keysharing:masterkey().
|
||||
|
||||
decrypt_and_reconstruct(EncryptedMasterKeyShares, EncPrivateKeys, Threshold) ->
|
||||
{ThresholdEncryptedMasterKeyShares, _} = lists:split(Threshold, EncryptedMasterKeyShares),
|
||||
Shares = lists:foldl(
|
||||
fun (#{id := Id, encrypted_share := EncryptedShare}, Acc) ->
|
||||
EncPrivateKey = maps:get(Id, EncPrivateKeys),
|
||||
DecryptedShare = kds_crypto:private_decrypt(EncPrivateKey, EncryptedShare),
|
||||
[DecryptedShare | Acc]
|
||||
end,
|
||||
[],
|
||||
ThresholdEncryptedMasterKeyShares
|
||||
),
|
||||
case kds_keysharing:recover(Shares) of
|
||||
{ok, MasterKey} ->
|
||||
MasterKey;
|
||||
{error, failed_to_recover} ->
|
||||
_ = logger:error("failed to recover Shares: ~p~nEncryptedMasterKeyShares: ~p",
|
||||
[Shares, EncryptedMasterKeyShares]),
|
||||
throw(recover_error)
|
||||
end.
|
||||
|
||||
-spec validate_init([{kds_shareholder:shareholder_id(), kds_keysharing:masterkey_share()}], config()) -> ok.
|
||||
|
||||
validate_init([{Id, DecryptedMasterKeyShare} | []], C) ->
|
||||
@ -97,6 +125,14 @@ rotate(C) ->
|
||||
{more_keys_needed, 1} = kds_keyring_client:confirm_rotate(Id1, MasterKey1, root_url(C)),
|
||||
ok = kds_keyring_client:confirm_rotate(Id2, MasterKey2, root_url(C)).
|
||||
|
||||
-spec marshall_old_format(term()) -> binary().
|
||||
marshall_old_format(#{current_key := CurrentKey, keys := Keys}) ->
|
||||
<<CurrentKey, (maps:fold(fun marshall_keys/3, <<>>, Keys))/binary>>.
|
||||
|
||||
-spec marshall_keys(byte(), binary(), binary()) -> binary().
|
||||
marshall_keys(KeyId, Key, Acc) ->
|
||||
<<Acc/binary, KeyId, Key:32/binary>>.
|
||||
|
||||
config(Key, Config) ->
|
||||
config(Key, Config, undefined).
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
-export([init_with_cancel/1]).
|
||||
-export([lock/1]).
|
||||
-export([unlock/1]).
|
||||
-export([unlock_old_keyring/1]).
|
||||
-export([unlock_with_timeout/1]).
|
||||
-export([rekey/1]).
|
||||
-export([rekey_with_timeout/1]).
|
||||
@ -64,6 +65,8 @@ groups() ->
|
||||
{basic_lifecycle, [sequence], [
|
||||
init,
|
||||
lock,
|
||||
unlock_old_keyring,
|
||||
lock,
|
||||
unlock,
|
||||
rekey,
|
||||
rekey_with_timeout,
|
||||
@ -142,7 +145,8 @@ end_per_group(_, C) ->
|
||||
-spec init(config()) -> _.
|
||||
|
||||
init(C) ->
|
||||
EncryptedMasterKeyShares = kds_keyring_client:start_init(2, root_url(C)),
|
||||
Threshold = 2,
|
||||
EncryptedMasterKeyShares = kds_keyring_client:start_init(Threshold, root_url(C)),
|
||||
Shareholders = kds_shareholder:get_all(),
|
||||
_ = ?assertEqual(length(EncryptedMasterKeyShares), length(Shareholders)),
|
||||
EncPrivateKeys = enc_private_keys(C),
|
||||
@ -173,7 +177,9 @@ init(C) ->
|
||||
},
|
||||
kds_keyring_client:get_state(root_url(C))
|
||||
),
|
||||
kds_ct_utils:store(master_keys, DecryptedMasterKeyShares, C).
|
||||
MasterKey = kds_ct_keyring:decrypt_and_reconstruct(EncryptedMasterKeyShares, EncPrivateKeys, Threshold),
|
||||
ok = kds_ct_utils:store(master_keys, DecryptedMasterKeyShares, C),
|
||||
kds_ct_utils:store(master_key, MasterKey, C).
|
||||
|
||||
-spec init_with_timeout(config()) -> _.
|
||||
|
||||
@ -280,6 +286,17 @@ unlock(C) ->
|
||||
),
|
||||
_ = ?assertEqual(ok, kds_keyring_client:confirm_unlock(Id2, MasterKey2, root_url(C))).
|
||||
|
||||
-spec unlock_old_keyring(config()) -> _.
|
||||
|
||||
unlock_old_keyring(C) ->
|
||||
MasterKey = kds_ct_utils:lookup(master_key, C),
|
||||
KeyringStorageOpts = application:get_env(kds, keyring_storage_opts, #{}),
|
||||
KeyringPath = maps:get(keyring_path, KeyringStorageOpts, filename:join(config(priv_dir, C), "keyring")),
|
||||
MarshalledKeyring = kds_ct_keyring:marshall_old_format(#{current_key => 0, keys => #{0 => kds_crypto:key()}}),
|
||||
EncodedOldKeyring = kds_crypto:encrypt(MasterKey, MarshalledKeyring),
|
||||
ok = file:write_file(KeyringPath, EncodedOldKeyring),
|
||||
_ = unlock(C).
|
||||
|
||||
-spec unlock_with_timeout(config()) -> _.
|
||||
|
||||
unlock_with_timeout(C) ->
|
||||
|
Loading…
Reference in New Issue
Block a user