summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ebin/plop.app2
-rw-r--r--include/plop.hrl21
-rw-r--r--src/db.erl15
-rw-r--r--src/db.hrl4
-rw-r--r--src/plop.erl176
-rw-r--r--test/eckey-public.pem4
-rw-r--r--test/eckey.pem8
-rw-r--r--test/plop_test.erl108
8 files changed, 204 insertions, 134 deletions
diff --git a/ebin/plop.app b/ebin/plop.app
index 55d5648..dd40311 100644
--- a/ebin/plop.app
+++ b/ebin/plop.app
@@ -3,7 +3,7 @@
[{description, "The plop store"},
{vsn, "0.0.1"},
{modules, [plop_app, plop_sup, plop, db, ht, hex]},
- {applications, [kernel, stdlib, mnesia]}, % crypto, public_key, mnesia
+ {applications, [kernel, stdlib, mnesia]}, % crypto, public_key
{registered, [plop, db]},
{mod, {plop_app, []}} % <-- key file and pass phrase
]}.
diff --git a/include/plop.hrl b/include/plop.hrl
index 30a5385..8115374 100644
--- a/include/plop.hrl
+++ b/include/plop.hrl
@@ -35,21 +35,22 @@
}).
-type spt_signed() :: #spt_signed{}.
-%% %% Part of interface to plop:add/1.
-%% -record(plop_entry, {
-%% type :: entry_type(),
-%% data :: binary()
-%% }).
-%% -type plop_entry() :: #plop_entry{}.
-
-%% A data entry.
+%% A plop entry with timestamp. Part of the Merkle Tree Leaf
+%% structure.
-record(timestamped_entry, {
timestamp = now :: now | integer(),
- entry_type :: entry_type(),
- entry :: binary()
+ entry :: plop_entry()
}).
-type timestamped_entry() :: #timestamped_entry{}.
+%% An entry, without the timestamp. This is what we hash over and
+%% store in the the database for finding duplicated submissions.
+-record(plop_entry, {
+ type :: entry_type(),
+ data :: binary()
+ }).
+-type plop_entry() :: #plop_entry{}.
+
%% @doc The parts of an STH which is to be signed. Used as the
%% interface to plop:sth/1, for testing. Should probably be internal
%% to plop, if that can be arranged wrt testing.
diff --git a/src/db.erl b/src/db.erl
index 857615c..3529080 100644
--- a/src/db.erl
+++ b/src/db.erl
@@ -51,8 +51,7 @@ dump_to_file(Filename) ->
mnesia:dump_to_textfile(Filename).
init(_Args) ->
- {mnesia:wait_for_tables([plop], 5000),
- []}.
+ {mnesia:wait_for_tables([plop], 5000), []}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
@@ -100,4 +99,14 @@ handle_call({dump, Table}, _From, State) ->
Res = mnesia:transaction(F),
{reply, Res, State};
handle_call({find, Hash}, _From, State) ->
- {reply, mnesia:dirty_read({plop, Hash}), State}.
+ F = fun() ->
+ mnesia:select(plop,
+ [{#plop{hash = Hash, _='_'}, [], ['$_']}])
+ end,
+ {atomic, Result} = mnesia:transaction(F),
+ Record = case length(Result) of
+ 0 -> [];
+ 1 -> hd(Result);
+ _ -> duplicate_hash_in_db % FIXME: log an error
+ end,
+ {reply, Record, State}.
diff --git a/src/db.hrl b/src/db.hrl
index 16b9103..ce6df7b 100644
--- a/src/db.hrl
+++ b/src/db.hrl
@@ -2,7 +2,7 @@
%% '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{}.
+ hash :: binary(), % Hash over #plop_entry{} in 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 63545f0..5ca595f 100644
--- a/src/plop.erl
+++ b/src/plop.erl
@@ -16,6 +16,8 @@
-export([add/1, sth/0]).
%% API for tests.
-export([sth/1]).
+-export([read_keyfile_rsa/2, read_keyfiles_ec/2]).
+-export([testing_get_pubkey/0]).
%% gen_server callbacks.
-export([init/1, handle_call/3, terminate/2,
handle_cast/2, handle_info/2, code_change/3]).
@@ -26,8 +28,8 @@
-include_lib("eunit/include/eunit.hrl").
-define(PLOPVERSION, 1).
--define(TESTKEYFILE, "src/test/rsakey.pem").
--define(TESTKEYPASSPHRASE, "sikrit").
+-define(TESTPRIVKEYFILE, "test/eckey.pem").
+-define(TESTPUBKEYFILE, "test/eckey-public.pem").
-record(state, {pubkey :: public_key:rsa_public_key(),
privkey :: public_key:rsa_private_key(),
@@ -35,7 +37,7 @@
hashtree :: ht:head()}).
start_link() ->
- start_link(?TESTKEYFILE, ?TESTKEYPASSPHRASE). % FIXME: Remove.
+ start_link(?TESTPRIVKEYFILE, ?TESTPUBKEYFILE). % FIXME: Remove.
start_link(Keyfile, Passphrase) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [Keyfile, Passphrase], []).
@@ -43,10 +45,16 @@ stop() ->
gen_server:call(?MODULE, stop).
%%%%%%%%%%%%%%%%%%%%
-init([Keyfile, Passphrase]) ->
- {Private_key, Public_key} = read_keyfile(Keyfile, Passphrase),
- LogID = crypto:hash(sha256,
- public_key:der_encode('RSAPublicKey', Public_key)),
+init([PubKeyfile, PrivKeyfile]) ->
+ %% Read RSA keypair.
+ %% {Private_key, Public_key} = read_keyfile_rsa(Keyfile, Passphrase),
+ %% LogID = crypto:hash(sha256,
+ %% public_key:der_encode('RSAPublicKey', Public_key)),
+ %% Read EC keypair.
+ {Private_key, Public_key} = read_keyfiles_ec(PubKeyfile, PrivKeyfile),
+ LogID = crypto:hash(sha256, public_key:der_encode(
+ 'ECPoint',
+ element(2, element(1, Public_key)))), % FIXME!
{ok, #state{pubkey = Public_key,
privkey = Private_key,
logid = LogID,
@@ -74,6 +82,8 @@ sth() ->
sth(Data) ->
gen_server:call(?MODULE, {sth, Data}).
+testing_get_pubkey() ->
+ gen_server:call(?MODULE, {test, pubkey}).
%%%%%%%%%%%%%%%%%%%%
handle_call(stop, _From, State) ->
{stop, normal, stopped, State};
@@ -86,35 +96,46 @@ handle_call({add, #timestamped_entry{} = TimestampedEntry},
logid = LogID,
hashtree = Tree}) ->
{NewTree, SPT} = do_add(TimestampedEntry, Privkey, LogID, Tree),
- io:format("Index: ~p~nSPT: ~p~n", [ht:size(NewTree), SPT]),
{reply, SPT, State#state{hashtree = NewTree}};
handle_call({sth, Data}, _From,
Plop = #state{privkey = PrivKey,
hashtree = Tree}) ->
- {reply, sth(PrivKey, Tree, Data), Plop}.
+ {reply, sth(PrivKey, Tree, Data), Plop};
+
+handle_call({test, pubkey}, _From,
+ Plop = #state{pubkey = PK}) ->
+ {reply, PK, Plop}.
%%%%%%%%%%%%%%%%%%%%
-spec do_add(timestamped_entry(), public_key:rsa_private_key(), binary(), any()) -> {any(), binary()}.
-do_add(TimestampedEntry, Privkey, LogID, Tree) ->
- 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.
+do_add(TimestampedEntry = #timestamped_entry{entry = PlopEntry},
+ Privkey, LogID, Tree) ->
+ DB_hash = crypto:hash(sha256, serialise(PlopEntry)),
+ Record = db:find(DB_hash),
+ case Record of
+ #plop{index = I, mtl = M = #mtl{entry = E}, spt_text = SPT} ->
+ io:format("Found entry: index=~p~nMTL: ~p~nSPT: ~p~n", [I, M, SPT]),
+ Record = Record#plop{ % DB consistency checking.
+ hash = DB_hash,
+ mtl = #mtl{entry =
+ #timestamped_entry{
+ timestamp = E#timestamped_entry.timestamp,
+ entry = PlopEntry}
+ }},
{Tree, SPT}; % State not changed, cached SPT.
_ ->
NewSPT = spt(LogID, Privkey, TimestampedEntry),
+ MTL = #mtl{entry = TimestampedEntry},
+ io:format("Creating new entry: index=~p~ndb hash: ~p~nMTL: ~p~nSPT: ~p~n",
+ [ht:size(Tree) + 1, DB_hash, MTL, NewSPT]),
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.
+ {ht:append(Tree, serialise(MTL)), % New tree.
NewSPT} % New SPT.
end.
@@ -123,8 +144,7 @@ do_add(TimestampedEntry, Privkey, LogID, Tree) ->
-spec spt(binary(), public_key:rsa_private_key(), timestamped_entry()) -> binary().
spt(LogID, PrivKey, #timestamped_entry{
timestamp = Timestamp_in,
- entry_type = EntryType,
- entry = Entry
+ entry = #plop_entry{type = EntryType, data = EntryData}
}) ->
Timestamp = timestamp(Timestamp_in),
BinToSign =
@@ -133,18 +153,16 @@ spt(LogID, PrivKey, #timestamped_entry{
signature_type = certificate_timestamp,
timestamp = Timestamp,
entry_type = EntryType,
- signed_entry = Entry})),
+ signed_entry = EntryData})),
Signature = signhash(BinToSign, PrivKey),
SPT = serialise(#spt_on_wire{
version = ?PLOPVERSION,
logid = LogID,
timestamp = Timestamp,
signature = Signature}),
- io:format("SPT: ~p~nBinToSign: ~p~nSignature = ~p~n",
- [SPT, BinToSign, Signature]),
list_to_binary(SPT).
-%% @doc Signed Tree Head as described in RFC6962 section 3.2.
+%% @doc Signed Tree Head as specified in RFC6962 section 3.2.
sth(PrivKey, Tree, []) ->
sth(PrivKey, Tree, #sth{timestamp = now});
sth(PrivKey, Tree, #sth{version = Version, timestamp = Timestamp_in}) ->
@@ -166,24 +184,64 @@ sth(PrivKey, Tree, #sth{version = Version, timestamp = Timestamp_in}) ->
[STH, BinToSign, Signature, Timestamp]),
STH.
-read_keyfile(Filename, Passphrase) ->
+%% TODO: Merge the keyfile reading functions.
+
+%% Read one password protected PEM file with an RSA keypair.
+read_keyfile_rsa(Filename, Passphrase) ->
{ok, PemBin} = file:read_file(Filename),
- [Entry] = public_key:pem_decode(PemBin),
- Privatekey = public_key:pem_entry_decode(Entry, Passphrase),
+ [KeyPem] = public_key:pem_decode(PemBin), % Use first entry.
+ Privatekey = decode_key(KeyPem, Passphrase),
{Privatekey, public_key(Privatekey)}.
+%% Read two PEM files, one with a private EC key and one with the
+%% corresponding public EC key.
+read_keyfiles_ec(PrivkeyFile, Pubkeyfile) ->
+ {ok, PemBinPriv} = file:read_file(PrivkeyFile),
+ [OTPPubParamsPem, PrivkeyPem] = public_key:pem_decode(PemBinPriv),
+ Privatekey = decode_key(PrivkeyPem),
+
+ {_, ParamsBin, ParamsEnc} = OTPPubParamsPem,
+ PubParamsPem = {'EcpkParameters', ParamsBin, ParamsEnc},
+ Params = public_key:pem_entry_decode(PubParamsPem),
+
+ {ok, PemBinPub} = file:read_file(Pubkeyfile),
+ [SPKIPem] = public_key:pem_decode(PemBinPub),
+ %% SPKI is missing #'AlgorithmIdentifier' so pem_entry_decode won't do.
+ %% Publickey = public_key:pem_entry_decode(SPKIPem),
+ #'SubjectPublicKeyInfo'{algorithm = AlgoDer} = SPKIPem,
+ SPKI = public_key:der_decode('SubjectPublicKeyInfo', AlgoDer),
+ #'SubjectPublicKeyInfo'{subjectPublicKey = {_, Octets}} = SPKI,
+ Point = #'ECPoint'{point = Octets},
+ Publickey = {Point, Params},
+
+ {Privatekey, Publickey}.
+
+decode_key(Entry) ->
+ public_key:pem_entry_decode(Entry).
+decode_key(Entry, Passphrase) ->
+ public_key:pem_entry_decode(Entry, Passphrase).
+
public_key(#'RSAPrivateKey'{modulus = Mod, publicExponent = Exp}) ->
#'RSAPublicKey'{modulus = Mod, publicExponent = Exp}.
--spec signhash(iolist() | binary(), public_key:rsa_private_key()) -> binary().
-signhash(Data, PrivKey) ->
- %% Was going to just crypto:sign/3 the hash but looking at
- %% digitally_signed() in lib/ssl/src/ssl_handshake.erl it seems
- %% like we should rather use (undocumented) encrypt_private/3.
- %public_key:sign(hash(sha256, BinToSign), sha256, PrivKey)
- public_key:encrypt_private(crypto:hash(sha256, Data),
- PrivKey,
- [{rsa_pad, rsa_pkcs1_padding}]).
+
+%% FIXME: Merge RSA and DC.
+signhash(D, K) ->
+ signhash_ec(D, K).
+
+-spec signhash_ec(iolist() | binary(), public_key:ec_private_key()) -> binary().
+signhash_ec(Data, PrivKey) ->
+ public_key:sign(Data, sha256, PrivKey).
+
+%% -spec signhash_rsa(iolist() | binary(), public_key:rsa_private_key()) -> binary().
+%% signhash_rsa(Data, PrivKey) ->
+%% %% Was going to just crypto:sign/3 the hash but looking at
+%% %% digitally_signed() in lib/ssl/src/ssl_handshake.erl it seems
+%% %% like we should rather use (undocumented) encrypt_private/3.
+%% %public_key:sign(hash(sha256, BinToSign), sha256, PrivKey)
+%% public_key:encrypt_private(crypto:hash(sha256, Data),
+%% PrivKey,
+%% [{rsa_pad, rsa_pkcs1_padding}]).
%%%%%%%%%%%%%%%%%%%%
%% Serialisation of data.
@@ -216,16 +274,20 @@ timestamp(Timestamp) ->
_ -> Timestamp
end.
--spec serialise(timestamped_entry() | spt_on_wire() | spt_signed() | mtl() | sth()) -> iolist().
+-spec serialise(plop_entry() | timestamped_entry() | spt_on_wire() | spt_signed() | mtl() | sth()) -> iolist().
+serialise(#plop_entry{
+ type = TypeAtom,
+ data = Data
+ }) ->
+ EntryType = entry_type(TypeAtom),
+ [<<EntryType:16,
+ Data/binary>>];
serialise(#timestamped_entry{
timestamp = Timestamp,
- entry_type = TypeAtom,
- entry = Entry
+ entry = PlopEntry
}) ->
- EntryType = entry_type(TypeAtom),
- [<<Timestamp:64,
- EntryType:16,
- Entry/binary>>];
+ [<<Timestamp:64>>,
+ serialise(PlopEntry)];
serialise(#spt_on_wire{
version = Version,
logid = LogID,
@@ -285,14 +347,30 @@ serialise_test_() ->
timestamp = 0,
entry_type = x509,
signed_entry = <<"foo">>})))].
-add_test_() ->
- {ok, S} = init([?TESTKEYFILE, ?TESTKEYPASSPHRASE]),
+%%add_test_() ->
+add_test() ->
+ {ok, S} = init([?TESTPRIVKEYFILE, ?TESTPUBKEYFILE]),
+
+ Data1 = <<"some data">>,
{_Tree, SPT} =
do_add(#timestamped_entry{
timestamp = 4711,
- entry_type = test,
- entry = <<"some data">>},
+ entry = #plop_entry{type = test, data = Data1}},
+ S#state.privkey,
+ S#state.logid,
+ S#state.hashtree),
+ {_Tree1, SPT1} =
+ do_add(#timestamped_entry{
+ timestamp = 4712,
+ entry = #plop_entry{type = test, data = Data1}},
S#state.privkey,
S#state.logid,
S#state.hashtree),
- [?_assertEqual(<<"fixme:SPT">>, SPT)].
+ ?assertEqual(SPT, SPT1),
+
+ TE = #timestamped_entry{
+ timestamp = 0,
+ entry = #plop_entry{type = test, data = <<"some data">>}},
+ SPTeq1 = spt(S#state.logid, S#state.privkey, TE),
+ SPTeq2 = spt(S#state.logid, S#state.privkey, TE),
+ ?assertNotEqual(SPTeq1, SPTeq2). % DSA signatures differ!
diff --git a/test/eckey-public.pem b/test/eckey-public.pem
new file mode 100644
index 0000000..d952d7e
--- /dev/null
+++ b/test/eckey-public.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4qWq6afhBUi0OdcWUYhyJLNXTkGq
+Q9PMS5lqoCgkV2h1ZvpNjBH2u8UbgcOQwqDo66z6BWQJGolozZYmNHE2kQ==
+-----END PUBLIC KEY-----
diff --git a/test/eckey.pem b/test/eckey.pem
new file mode 100644
index 0000000..ed24cfa
--- /dev/null
+++ b/test/eckey.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIMM/FjZ4FSzfENTTwGpTve6CP+IVrY7p8OKV634uJI/foAoGCCqGSM49
+AwEHoUQDQgAE4qWq6afhBUi0OdcWUYhyJLNXTkGqQ9PMS5lqoCgkV2h1ZvpNjBH2
+u8UbgcOQwqDo66z6BWQJGolozZYmNHE2kQ==
+-----END EC PRIVATE KEY-----
diff --git a/test/plop_test.erl b/test/plop_test.erl
index 79dbbd3..cbbc85c 100644
--- a/test/plop_test.erl
+++ b/test/plop_test.erl
@@ -2,20 +2,20 @@
-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}}.
+%% 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).
+ %%Pid = start(),
+ Pubkey = plop:testing_get_pubkey(),
+ add(0, Pubkey),
+ add(1, Pubkey),
+ sth(0, Pubkey).
+ %%stop(Pid).
%%% Setup.
start() ->
@@ -31,49 +31,29 @@ is_registered(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>>,
+add(0, Pubkey) ->
+ Msg = <<"some data">>,
Entry = #timestamped_entry{timestamp = 4711,
- entry_type = test,
- entry = <<"some data">>},
+ entry = #plop_entry{type = test,
+ data = Msg}},
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>>,
+ <<Version:8, _LogID:256, Timestamp:64, Signature/binary>> = SPT,
+ Signed = <<1:8, 0:8, 4711:64, 2:16, Msg/binary>>,
+ ?assertEqual(1, Version),
+ ?assertEqual(4711, Timestamp),
+ ?assert(public_key:verify(Signed, sha256, Signature, Pubkey));
+
+add(1, Pubkey) ->
+ Msg = <<"some more data">>,
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).
+ entry = #plop_entry{type = test,
+ data = Msg}},
+ <<Version:8, _LogID:256, Timestamp:64, Signature/binary>> = plop:add(Entry),
+ Signed = <<1:8, 0:8, 4712:64, 2:16, Msg/binary>>,
+ ?assertEqual(1, Version),
+ ?assertEqual(4712, Timestamp),
+ ?assert(public_key:verify(Signed, sha256, Signature, Pubkey)).
+
%% add(2) ->
%% TestVector = <<>>,
%% %% Same data as in 0, should not result in new database entry.
@@ -82,23 +62,13 @@ add(1) ->
%% ?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).
+sth(0, Pubkey) ->
+ STH = plop:sth(#sth{}),
+ %%io:format(element(2, file:open("testdata", write)), "~p", [STH]),
+ <<Treesize:64,
+ Timestamp:64,
+ Roothash:256,
+ Signature/binary>> = STH,
+ ?assertEqual(2, Treesize),
+ Data = <<1:8, 1:8, Timestamp:64, Treesize:64, Roothash:256>>,
+ ?assert(public_key:verify(Data, sha256, Signature, Pubkey)).