You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2020/04/09 16:17:41 UTC
[couchdb] 02/03: Cleanup and condense aegis
This is an automated email from the ASF dual-hosted git repository.
davisp pushed a commit to branch davisp-aegis
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit c8045d659779ff3dce4ef39e1c5769d1008faa40
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Thu Apr 9 11:16:51 2020 -0500
Cleanup and condense aegis
---
src/aegis/src/aegis.app.src | 33 ++++---
src/aegis/src/aegis.erl | 208 ++++++++++++++++----------------------------
2 files changed, 90 insertions(+), 151 deletions(-)
diff --git a/src/aegis/src/aegis.app.src b/src/aegis/src/aegis.app.src
index eb3018f..e052323 100644
--- a/src/aegis/src/aegis.app.src
+++ b/src/aegis/src/aegis.app.src
@@ -10,20 +10,19 @@
% License for the specific language governing permissions and limitations under
% the License.
-{application, aegis,
- [{description, "If it's good enough for Zeus, it's good enough for CouchDB"},
- {vsn, git},
- {registered, []},
- {applications,
- [kernel,
- stdlib,
- crypto,
- erlfdb
- ]},
- {env,[]},
- {modules, []},
-
- {maintainers, []},
- {licenses, []},
- {links, []}
- ]}.
+{application, aegis, [
+ {description, "If it's good enough for Zeus, it's good enough for CouchDB"},
+ {vsn, git},
+ {registered, []},
+ {applications, [
+ kernel,
+ stdlib,
+ crypto,
+ erlfdb
+ ]},
+ {env,[]},
+ {modules, []},
+ {maintainers, []},
+ {licenses, []},
+ {links, []}
+]}.
diff --git a/src/aegis/src/aegis.erl b/src/aegis/src/aegis.erl
index 5937b4c..9b4778d 100644
--- a/src/aegis/src/aegis.erl
+++ b/src/aegis/src/aegis.erl
@@ -12,9 +12,6 @@
-module(aegis).
--define(IS_AEGIS_FUTURE, {aegis_future, _}).
-%% encapsulation violation :/
--define(IS_FUTURE, {erlfdb_future, _, _}).
%% Assume old crypto api
-define(hmac(Key, PlainText), crypto:hmac(sha256, Key, PlainText)).
@@ -27,11 +24,12 @@
-ifdef(OTP_RELEASE).
-if(?OTP_RELEASE >= 22).
-undef(hmac).
--define(hmac(Key, PlainText), crypto:mac(hmac, sha256, Key, PlainText)).
-undef(aes_gcm_encrypt).
+-undef(aes_gcm_decrypt).
+
+-define(hmac(Key, PlainText), crypto:mac(hmac, sha256, Key, PlainText)).
-define(aes_gcm_encrypt(Key, IV, AAD, Data),
crypto:crypto_one_time_aead(aes_256_gcm, Key, IV, Data, AAD, 16, true)).
--undef(aes_gcm_decrypt).
-define(aes_gcm_decrypt(Key, IV, AAD, CipherText, CipherTag),
crypto:crypto_one_time_aead(aes_256_gcm, Key, IV, CipherText,
AAD, CipherTag, false)).
@@ -39,147 +37,89 @@
-endif.
-export([
- fold_range/6,
- fold_range/7,
- fold_range_future/5,
- fold_range_wait/4,
- get/3,
- get_range/4,
- get_range/5,
- get_range_startswith/3,
- get_range_startswith/4,
- set/4,
- wait/1
+ init/1,
+ encrypt/3,
+ decrypt/3,
+ decrypt/2,
+ wrap_fold/2
]).
-fold_range(EncryptionContext, DbOrTx, StartKey, EndKey, Fun, Acc) ->
- fold_range(EncryptionContext, DbOrTx, StartKey, EndKey, Fun, Acc, []).
-
-
-fold_range(EncryptionContext, DbOrTx, StartKey, EndKey, Fun, Acc, Options) ->
- validate_encryption_context(EncryptionContext),
- erlfdb:fold_range(DbOrTx, StartKey, EndKey, decrypt_fun(EncryptionContext, Fun), Acc, Options).
-
-
-fold_range_future(EncryptionContext, TxOrSs, StartKey, EndKey, Options) ->
- validate_encryption_context(EncryptionContext),
- Future = erlfdb:fold_range_future(TxOrSs, StartKey, EndKey, Options),
- {aegis_fold_future, EncryptionContext, Future}.
-
-
-fold_range_wait(Tx, {aegis_fold_future, EncryptionContext, Future}, Fun, Acc) ->
- validate_encryption_context(EncryptionContext),
- erlfdb:fold_range_wait(Tx, Future, decrypt_fun(EncryptionContext, Fun), Acc).
-
-
-get(EncryptionContext, DbOrTx, Key) ->
- validate_encryption_context(EncryptionContext),
- Result = erlfdb:get(DbOrTx, Key),
- decrypt(EncryptionContext, Key, Result).
-
-
-get_range(EncryptionContext, DbOrTx, StartKey, EndKey) ->
- get_range(EncryptionContext, DbOrTx, StartKey, EndKey, []).
-
-
-get_range(EncryptionContext, DbOrTx, StartKey, EndKey, Options) ->
- validate_encryption_context(EncryptionContext),
- Result = erlfdb:get_range(DbOrTx, StartKey, EndKey, Options),
- decrypt(EncryptionContext, Result).
-
-
-get_range_startswith(EncryptionContext, DbOrTx, Prefix) ->
- get_range_startswith(EncryptionContext, DbOrTx, Prefix, []).
-
-
-get_range_startswith(EncryptionContext, DbOrTx, Prefix, Options) ->
- validate_encryption_context(EncryptionContext),
- Result = erlfdb:get_range_startswith(DbOrTx, Prefix, Options),
- decrypt(EncryptionContext, Result).
-
-
-set(EncryptionContext, DbOrTx, Key, Value) ->
- validate_encryption_context(EncryptionContext),
- erlfdb:set(DbOrTx, Key, encrypt(EncryptionContext, Key, Value)).
-
-
-wait({aegis_future, EncryptionContext, Future}) ->
- Value = erlfdb:wait(Future),
- decrypt(EncryptionContext, Value);
-
-wait({aegis_future, EncryptionContext, Key, Future}) ->
- Value = erlfdb:wait(Future),
- decrypt(EncryptionContext, Key, Value);
-
-wait(Result) ->
- Result.
-
-
-%% Private functions
-
-validate_encryption_context(#{uuid := _UUID}) ->
- ok;
-validate_encryption_context(_) ->
- error(invalid_encryption_context).
-
-
-define(DUMMY_KEY, <<1:256>>).
-
-encrypt(#{uuid := UUID}, Key, Value) ->
- {CipherText, <<CipherTag:128>>} =
- ?aes_gcm_encrypt(
- derive(?DUMMY_KEY, Key),
- <<0:96>>,
- UUID,
- Value),
+-define(AEGIS_KEY_DOOHICKIES, 254).
+
+
+create(#{} = Db) ->
+ #{
+ tx = Tx,
+ db_prefix = DbPrefix
+ } = Db,
+ DbKeyThinger = erlfdb_tuple:pack({?AEGIS_KEY_DOOHICKIES}, DbPrefix),
+ MyThingAMaJig = oooh_look_at_my_fancy_math(UUID, MathStuff),
+ ok = erlfdb:set(Tx, DbKeyThinger, MyThingAMaJig),
+ Db#{
+ aegis_ctx = MyThingAMaJig
+ }.
+
+
+open(#{} = Db) ->
+ #{
+ tx = Tx,
+ db_prefix = DbPrefix
+ } = Db,
+ DbKeyThinger = erlfdb_tuple:pack({?AEGIS_KEY_DOOHICKIES}, DbPrefix),
+ MyLookupThing = erlfdb:wait(erlfdb:get(Tx, DbKeyThinger)),
+ Db#{
+ aegis_ctx => MyLookupThing
+ }.
+
+
+encrypt(#{} = Db, Key, Value) ->
+ #{
+ aegis_ctx = Ctx,
+ uuid := UUID
+ } = Db,
+ DerivedKey = derive(?DUMMY_KEY, Key),
+ {CipherText, <<CipherTag:128>>} = ?aes_gcm_encrypt(
+ Derived,
+ <<0:96>>,
+ UUID,
+ Value
+ ),
<<1:8, CipherTag:128, CipherText/binary>>.
-decrypt(EncryptionContext, ?IS_FUTURE = Future) ->
- decrypt_future(EncryptionContext, Future);
+decrypt(#{} = Db, Key, Value) when is_binary(Key), is_binary(Value) ->
+ #{
+ aegis_ctx = Ctx,
+ uuid := UUID
+ } = Db,
+ <<1:8, CipherTag:128, CipherText/binary>> = Value,
+ Derived = derive(?DUMMY_KEY, Key),
+ Decrypted = ?aes_gcm_decrypt(
+ Derived,
+ <<0:96>>,
+ UUID,
+ CipherText,
+ <<CipherTag:128>>
+ ),
+ if Decrypted /= error -> Decrypted; true ->
+ erlang:error(decryption_failed)
+ end.
-decrypt(EncryptionContext, {Key, Value})
- when is_binary(Key), is_binary(Value) ->
- decrypt(EncryptionContext, Key, Value);
-decrypt(EncryptionContext, Rows) when is_list(Rows) ->
- [{Key, decrypt(EncryptionContext, Row)} || {Key, _} = Row <- Rows].
+decrypt(Db, {Key, Value}) ->
+ {Key, decrypt(Db, Key, Value)};
+decrypt(Db, Rows) when is_list(Rows) ->
+ lists:map(fun({Key, Value}) ->
+ decrypt(Db, {Key, Value})
+ end, Rows).
-decrypt(EncryptionContext, Key, ?IS_FUTURE = Future) ->
- decrypt_future(EncryptionContext, Key, Future);
-decrypt(#{uuid := UUID}, Key, Value) when is_binary(Value) ->
- <<1:8, CipherTag:128, CipherText/binary>> = Value,
- Decrypted =
- ?aes_gcm_decrypt(
- derive(?DUMMY_KEY, Key),
- <<0:96>>,
- UUID,
- CipherText,
- <<CipherTag:128>>),
- case Decrypted of
- error ->
- erlang:error(decryption_failed);
- Decrypted ->
- Decrypted
- end;
-
-decrypt(_EncryptionContext, _Key, Value) when not is_binary(Value) ->
- Value.
-
-
-decrypt_future(EncryptionContext, ?IS_FUTURE = Future) ->
- {aegis_future, EncryptionContext, Future}.
-
-decrypt_future(EncryptionContext, Key, ?IS_FUTURE = Future) ->
- {aegis_future, EncryptionContext, Key, Future}.
-
-decrypt_fun(EncryptionContext, Fun) ->
- fun(Rows, Acc) ->
- Fun(decrypt(EncryptionContext, Rows), Acc)
- end.
+wrap_fold_fun(Db, Fun) when is_function(Fun, 2)->
+ fun({Key, Val}, Acc) -> Fun(decrypt(Db, {Key, Value}), Acc) end.
+
derive(KEK, KeyMaterial) when bit_size(KEK) == 256 ->
PlainText = <<1:16, "aegis", 0:8, KeyMaterial/binary, 256:16>>,