diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/db.erl | 16 | ||||
-rw-r--r-- | src/db.hrl | 8 | ||||
-rw-r--r-- | src/plop.erl | 49 | ||||
l--------- | src/plop.hrl | 1 | ||||
-rw-r--r-- | src/plop_app.erl | 6 | ||||
-rw-r--r-- | src/plop_sup.erl | 2 | ||||
-rw-r--r-- | src/test/plop_test.erl | 104 | ||||
-rw-r--r-- | src/test/rsakey.pem | 30 |
8 files changed, 49 insertions, 167 deletions
@@ -12,27 +12,30 @@ code_change/3]). -include_lib("stdlib/include/qlc.hrl"). +-include("db.hrl"). -include("plop.hrl"). %% @doc Set up a database schema on all nodes that are to be included %% in the "database cluster". Has to be run _before_ mnesia has been %% started. init_db() -> - init_db([]). + init_db([node()]). init_db(Nodes) -> - mnesia:create_schema([node()] ++ Nodes), - init_tables(Nodes). + ok = mnesia:create_schema(Nodes), + rpc:multicall(Nodes, application, start, [mnesia]), + init_tables(Nodes), + rpc:multicall(Nodes, application, stop, [mnesia]). %% @doc Run once, or rather every time you start on a new database. %% If run more than once, we'll get {aborted, {already_exists, TABLE}}. init_tables() -> - init_tables([]). + init_tables([node()]). init_tables(Nodes) -> %% We've once upon a time invoked mnesia:create_schema/1 with the %% nodes that will be part of the database. RamCopies = [], DiscCopies = [], - DiscOnlyCopies = [node()] ++ Nodes, + DiscOnlyCopies = Nodes, mnesia:start(), mnesia:create_table(plop, [{type, set}, {ram_copies, RamCopies}, @@ -48,7 +51,8 @@ dump_to_file(Filename) -> mnesia:dump_to_textfile(Filename). init(_Args) -> - {ok, []}. % TODO: return state + {mnesia:wait_for_tables([plop], 5000), + []}. start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). diff --git a/src/db.hrl b/src/db.hrl new file mode 100644 index 0000000..16b9103 --- /dev/null +++ b/src/db.hrl @@ -0,0 +1,8 @@ +%% @doc What's stored in the database. +%% 'index' is the primary key, 'hash' is also indexed. +-record(plop, { + index :: non_neg_integer(), % Primary key. + hash :: binary(), % Hash over mtl. + mtl :: mtl(), % Merkle Tree Leaf, an #mtl{}. + spt_text :: binary() % Signed Plop Timestamp, an #spt_on_wire{}. + }). diff --git a/src/plop.erl b/src/plop.erl index a55e4ca..63545f0 100644 --- a/src/plop.erl +++ b/src/plop.erl @@ -21,6 +21,7 @@ handle_cast/2, handle_info/2, code_change/3]). -include("plop.hrl"). +-include("db.hrl"). -include_lib("public_key/include/public_key.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -95,29 +96,27 @@ handle_call({sth, Data}, _From, %%%%%%%%%%%%%%%%%%%% +-spec do_add(timestamped_entry(), public_key:rsa_private_key(), binary(), any()) -> {any(), binary()}. do_add(TimestampedEntry, Privkey, LogID, Tree) -> - H = crypto:hash(sha256, serialise(TimestampedEntry)), - Record = db:find(H), - TmpFixm = case Record of - #plop{index = I, spt = S} -> - io:format("Found entry w/ index=~p, SPT: ~p~n", [I, S]), - %% DB consistency check: - %%Record = #plop{hash = H, spt = serialise(Data)}, % FIXME: Remove. - {Tree, % State not changed. - S}; % Cached SPT. - _ -> - NewSPT = spt(LogID, Privkey, TimestampedEntry), - DbData = #plop{index = ht:size(Tree) + 1, - hash = H, - spt = NewSPT}, - db:add(DbData), - LeafData = #mtl{version = 1, - leaf_type = timestamped_entry, - entry = TimestampedEntry}, - {ht:append(Tree, serialise(LeafData)), % New tree. - NewSPT} % New SPT. - end, - TmpFixm. + MTL = #mtl{entry = TimestampedEntry}, + MTL_text = serialise(MTL), + DB_hash = crypto:hash(sha256, MTL_text), + case db:find(DB_hash) of + #plop{index = I, mtl = M, spt_text = SPT} -> + io:format("Found entry: index=~p, MTL: ~p, SPT: ~p~n", [I, M, SPT]), + %% DB consistency check: + %%Record = #plop{hash = H, spt = serialise(Data)}, % FIXME: Remove. + {Tree, SPT}; % State not changed, cached SPT. + _ -> + NewSPT = spt(LogID, Privkey, TimestampedEntry), + DB_data = #plop{index = ht:size(Tree) + 1, + hash = DB_hash, + mtl = MTL, + spt_text = NewSPT}, + db:add(DB_data), + {ht:append(Tree, MTL_text), % New tree. + NewSPT} % New SPT. + end. %% @doc Signed Plop Timestamp, conformant to an SCT in RFC6962 3.2 and %% RFC5246 4.7. @@ -288,12 +287,12 @@ serialise_test_() -> signed_entry = <<"foo">>})))]. add_test_() -> {ok, S} = init([?TESTKEYFILE, ?TESTKEYPASSPHRASE]), - [?_assertEqual( - <<"fixme">>, + {_Tree, SPT} = do_add(#timestamped_entry{ timestamp = 4711, entry_type = test, entry = <<"some data">>}, S#state.privkey, S#state.logid, - S#state.hashtree))]. + S#state.hashtree), + [?_assertEqual(<<"fixme:SPT">>, SPT)]. diff --git a/src/plop.hrl b/src/plop.hrl new file mode 120000 index 0000000..38dfcbf --- /dev/null +++ b/src/plop.hrl @@ -0,0 +1 @@ +/home/linus/usr/src/plop/include/plop.hrl
\ No newline at end of file diff --git a/src/plop_app.erl b/src/plop_app.erl index d2e99ac..0a972cc 100644 --- a/src/plop_app.erl +++ b/src/plop_app.erl @@ -1,8 +1,12 @@ -module(plop_app). -behaviour(application). -export([start/2, stop/1]). +-export([install/1]). -start(_Type, Args) -> +install(Nodes) -> + db:init_db(Nodes). + +start(normal, Args) -> plop_sup:start_link(Args). stop(_State) -> diff --git a/src/plop_sup.erl b/src/plop_sup.erl index 18ed926..3d0e66d 100644 --- a/src/plop_sup.erl +++ b/src/plop_sup.erl @@ -18,7 +18,7 @@ init(_Args) -> [{the_plop, {plop, start_link, []}, % Here's where key file name and pass phrase go. permanent, - 10000, % Shut down in 10s. + 10000, % Shut down within 10s. worker, [plop]}, {the_db, {db, start_link, []}, diff --git a/src/test/plop_test.erl b/src/test/plop_test.erl deleted file mode 100644 index 8a308c0..0000000 --- a/src/test/plop_test.erl +++ /dev/null @@ -1,104 +0,0 @@ --module(plop_test). --include("plop.hrl"). --include_lib("eunit/include/eunit.hrl"). - -start_stop_test_() -> - {"The server can be started, stopped and is regsitered", - {setup, fun start/0, fun stop/1, fun is_registered/1}}. - -%% "Entries can be added and the STH changes." -%% FIXME: This way, if a test fails, we don't stop plop. The tests -%% must run and be validated in strict order though. -adding_verifying_test() -> - Pid = start(), - add(0), - sth(0), - add(1), - %% sth(), - stop(Pid). - -%%% Setup. -start() -> - {ok, Pid} = plop:start_link("test/rsakey.pem", "sikrit"), - Pid. - -stop(_) -> - plop:stop(). - -%%% Tests. -is_registered(Pid) -> - [?_assert(erlang:is_process_alive(Pid)), - ?_assertEqual(Pid, whereis(plop))]. - -%%% Helpers. -add(0) -> - TestVector = - <<1,247,141,118,3,148,171,128,29,143,106,97,200,179,204,166,242,98,70,185,231, - 78,193,39,12,245,82,254,230,136,69,69,0,0,0,0,0,0,0,18,103,69,73,8,105,107, - 47,97,130,137,92,201,148,11,68,203,103,216,217,249,38,109,208,23,55,107,21, - 110,128,207,151,46,4,178,228,74,5,247,64,180,85,122,236,127,97,226,50,124, - 212,251,227,65,248,18,36,124,252,103,24,35,99,180,207,126,63,116,149,21,86, - 255,197,248,212,93,100,123,161,159,94,29,112,23,246,98,3,124,89,135,234,71, - 246,21,93,152,214,209,58,25,52,132,219,22,0,38,237,226,118,1,168,86,218,18, - 112,227,11,25,199,15,151,246,253,7,91,72,88,169,164,79,143,160,157,241,168, - 15,230,1,216,93,67,24,230,106,203,61,115,100,172,238,165,236,198,222,33,126, - 12,163,226,165,161,232,106,39,94,93,247,2,164,163,72,34,236,228,168,53,19, - 128,111,78,34,54,166,95,78,11,131,241,191,254,82,225,72,68,111,229,169,24,75, - 90,254,167,119,10,136,211,20,178,251,244,124,87,223,61,102,244,143,98,213,59, - 217,84,80,64,22,209,1,63,64,185,63,13,115,43,36,143,93,19,206,234,100,181, - 203,214,189,144,145,21,247,165,125,192,43,94,247,209,81,50,100>>, - Entry = #timestamped_entry{timestamp = 4711, - entry_type = test, - entry = <<"some data">>}, - SPT = plop:add(Entry), - ?assertEqual(TestVector, SPT); -add(1) -> - TestVector = - <<1,247,141,118,3,148,171,128,29,143,106,97,200,179,204,166,242,98,70,185,231, - 78,193,39,12,245,82,254,230,136,69,69,0,0,0,0,0,0,0,18,104,141,82,14,84,52, - 131,244,51,145,16,7,238,168,117,8,184,95,165,94,116,234,87,145,43,39,223,243, - 33,159,238,239,195,203,246,232,147,125,234,34,147,83,254,253,248,133,49,81, - 80,7,104,23,24,147,24,116,147,183,20,58,165,53,147,196,226,250,135,18,115, - 182,139,194,190,60,97,103,240,188,86,184,194,21,75,79,136,84,62,53,123,44, - 236,244,24,190,207,193,42,156,230,135,174,90,195,89,174,185,228,129,148,78, - 255,168,104,73,142,85,11,239,222,227,213,208,99,31,12,177,223,187,11,216,119, - 29,231,67,82,140,103,181,173,71,246,112,57,121,153,204,1,249,251,172,26,77, - 96,223,129,102,14,160,115,10,87,105,234,21,99,65,125,198,35,104,160,43,25,74, - 159,64,236,226,126,208,88,199,60,12,88,36,214,174,110,147,215,142,1,205,77, - 116,119,47,222,87,84,99,78,131,212,247,138,156,190,211,244,184,140,46,202,13, - 217,28,20,109,8,129,62,226,37,51,123,94,151,151,47,96,111,122,118,178,242,14, - 213,35,184,204,165,157,199,1,210,74,243,180,36,85,163,69,166,79,136>>, - Entry = #timestamped_entry{timestamp = 4712, - entry_type = test, - entry = <<"some more data">>}, - SPT = plop:add(Entry), - %%io:format(element(2, file:open("foo", write)), "~p", [SPT]), - ?assertEqual(TestVector, SPT). -%% add(2) -> -%% TestVector = <<>>, -%% %% Same data as in 0, should not result in new database entry. -%% Entry = #timestamped_entry{timestamp = 4713, entry_type = test, entry = <<"some data">>}, -%% SPT = plop:add(#spt{signature_type = test, entry = Entry}), -%% ?assertEqual(TestVector, SPT), -%% ?assertEqual(fixme, fixme). - -sth(0) -> - TestVector = - <<0,0,0,0,0,0,0,1,0,0,0,0,0,0,18,103,93,90,159,157,211,129,96,54,161,145,226, - 218,28,127,43,87,221,243,153,101,255,249,156,114,234,50,84,163,183,64,215, - 227,16,126,61,255,54,243,5,185,250,149,18,30,228,16,48,168,252,213,27,205, - 254,157,72,230,112,65,150,187,18,215,17,249,72,18,38,159,217,49,159,177,153, - 175,86,139,158,29,24,202,126,203,88,216,19,205,237,172,48,9,113,228,231,170, - 131,38,155,185,188,232,215,15,54,93,254,173,100,13,115,172,161,7,106,226,180, - 168,81,245,47,10,59,14,25,26,23,80,11,227,147,115,216,173,93,63,232,50,213, - 43,148,71,149,104,32,10,217,108,182,194,88,12,153,187,42,190,154,203,114,200, - 24,137,106,65,51,25,162,178,24,199,155,215,208,115,5,239,64,189,69,0,196,55, - 211,91,12,83,132,131,84,92,146,124,125,117,74,62,7,162,230,37,13,45,122,183, - 112,207,227,240,152,190,181,168,96,210,252,59,144,12,141,46,18,18,51,226,14, - 218,17,255,212,136,198,154,69,64,232,234,249,2,232,45,165,206,157,195,77,254, - 126,173,10,12,184,21,55,111,183,15,2,251,177,220,139,35,20,148,219,137,78, - 187,221,242,23,254,196,182,98,110,150,95,126,53,42,243,123,198,30,247,79,17, - 172,129>>, - STH = plop:sth(#sth{timestamp = 4711}), - io:format(element(2, file:open("testdata", write)), "~p", [STH]), - ?assertEqual(TestVector, STH). diff --git a/src/test/rsakey.pem b/src/test/rsakey.pem deleted file mode 100644 index 8e3fc97..0000000 --- a/src/test/rsakey.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,1DF607A561756223 - -REwpVd1/3Z/5BZ78/pzbWhSIY1ncFPGooHDEZtHzwnthAEzHvKFqDmCzvN9/HozD -zmb2NbZag4/jbSBFGVqQzGIsnz11pLiyLSAjfoSC1sREJ9XCInF7F1xBUluL5rJB -62pOVVfmoQqOk3hyIiwLzEneagFDMoZXPwkoCmda7sT1uLoo94zAzkhcoeP9rohm -5ssI4woebqwgLDlX/LvLQjbmvAPdtqb2FApH3FTvlqJbPBWPVRQSYMhM32FJPmbC -gPEpZJa1wfMu4bULHw0/GYtlb5MvoNDNe+NxnDpG88Gkh+qFQvARDGLwnuHttrQD -YTWqCPaAd3qaZSNgau2QYEXiOyTKYhPJhgPNTKN3BTx8w7Msk/OoXCKAfuNjsi3a -iX0AmloIMmZUMkk2rsfiGfy8C3buVvdJ7trcUrSm3+QfQVOvPdCSFj96r0iBG9C0 -klQvilVMnd/M1Uk2DCG2rP4HV4DO3fSVx6Vbyl2MqPZgPZkvdrBZThhXsgIFkNlX -WUtpbcscBmQFJlRNUbGT/syVWYSIhpvZBwWj9stY+Tn2jmQ+TUO9Xr7NG3PpJ8J+ -jFU1b30DF6OC9BQ4yPDqXzRshyRpafs7SXgGUOAiLESIs+/HrL5hKAmv+Wb0pb2x -PQ+p0Rsk9aRocODb1pkeRFKJT+sKR1LfaIgwPDhU7HHJp8OQxPdT2pYjpvpxFcb4 -+2MKnfideWIxux7yfFrLUbPh5DqWRIspNsxNagelj/EY6uTaBZdnMumkTgVXyD2Q -tS9LQFYJ7HrxWdZLHrybd7TJlch0dTr9Q+ToSkZq7WAn2qlcs13tVD+ns64u4TFR -KZ5ayA6K7CJzIBVEI4ZymAKvaHTyGcCi7lEcMj0vfps/gjr6+uJ4KnGBrqvAZXoz -oXsIpcJvSPf6IR1mB5NyCVs1aAZ1WGSuA1uTMjLyjmugWFg4dvVGL5nMRcOC2AEM -ayhy9Lref6YxkDIGktkIsZRcUcySK5w4c8xTNoYo/a8sh7zkTjaHFWcw+Ur5AmBx -A7VdQIGyBRtXoJZ9wNyNWqB88Pspo7u/EarAR+fowr8Wtlad7Dm1FAScObCCGiPQ -rbkJ0tzGdNZqJoe37lJ9EznsLUfgGQI/3HyTp9uwPOLfyTeR8adjop6QbMXazBNI -Yqvo58H/QwGxQIg/BdgQW64h4ruVcXFd5YFfzJO9cTH+g2CsFAkeYjU4IcZE6pN6 -BILWKIYhxbYLvjIyigyEhRQbQPKEtViONc02l5cwvN163+wo/1LcdwrXEAAbglPk -8Ka1bkTapk3kH3qJZjiarHoLugQXcSi3clcFkgC8U7+orf3iRQcNn96hzIz/uX9k -BvLFq5lsQKjfhFhUdS07cQM4CLbBVPE9FSiGw37QBeP4HLPf0YIbVy3Ggv12psO7 -/sr+gXqqKFvriCoLhThyW6izm3LTVoGjGN8O+RD/yyBnIfl/8WT+ioyEbSyvGBEr -GgSsAagkoMRj8mFXMWgN042k1Uu28cSQ5xVQAHnNXePljTDTPXbUffSW2zLAc1yJ -p6ga/eX3bFUCZqIwKbsJw/Q1eh3AeG4krtlKHbylH9ShLGNMNbYviCXs4LUD4zu7 ------END RSA PRIVATE KEY----- |