From 9eaa1ef1b558043b809fd7c7f869128c186ec0e9 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Mon, 2 Mar 2015 19:15:09 +0100 Subject: Implement external signing --- src/plop.erl | 4 ++-- src/sign.erl | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/signing.erl | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 src/signing.erl diff --git a/src/plop.erl b/src/plop.erl index 63579d1..5eb0c1f 100644 --- a/src/plop.erl +++ b/src/plop.erl @@ -132,7 +132,7 @@ spt(Data) -> #signature{algorithm = #sig_and_hash_alg{ hash_alg = sha256, signature_alg = ecdsa}, - signature = sign:sign(Data)}. + signature = sign:sign_sct(Data)}. consistency(TreeSizeFirst, TreeSizeSecond) -> TreeSize = db:size(), @@ -314,7 +314,7 @@ sth(#sth_signed{version = Version, timestamp = Timestamp_in}) -> algorithm = #sig_and_hash_alg{ hash_alg = sha256, signature_alg = ecdsa}, - signature = sign:sign(BinToSign)}, + signature = sign:sign_sth(BinToSign)}, STH = {Treesize, Timestamp, Roothash, Signature}, %%io:format("STH: ~p~nBinToSign: ~p~nSignature: ~p~nTimestamp: ~p~n", %% [STH, BinToSign, Signature, Timestamp]), diff --git a/src/sign.erl b/src/sign.erl index 9acb9d4..b0916fd 100644 --- a/src/sign.erl +++ b/src/sign.erl @@ -8,7 +8,7 @@ %% API. -export([start_link/0, stop/0]). --export([sign/1, get_pubkey/0, get_logid/0]). +-export([sign_sct/1, sign_sth/1, get_pubkey/0, get_logid/0]). -export([read_keyfile_ec/1]). %% API for tests. -export([read_keyfile_rsa/2]). @@ -16,6 +16,9 @@ -export([init/1, handle_call/3, terminate/2, handle_cast/2, handle_info/2, code_change/3]). +-define(CERTIFICATE_TIMESTAMP, 0). +-define(TREE_HASH, 1). + -import(stacktrace, [call/2]). -include_lib("public_key/include/public_key.hrl"). @@ -44,7 +47,6 @@ init([]) -> Private_key = read_keyfile_ec(PrivKeyfile), Public_key = read_keyfile_ec(PubKeyfile), LogID = read_keyfile_ec_logid(PubKeyfile), - _Tree = ht:reset_tree([db:size() - 1]), {ok, #state{pubkey = Public_key, privkey = Private_key, logid = LogID}}. @@ -107,17 +109,59 @@ public_key(#'RSAPrivateKey'{modulus = Mod, publicExponent = Exp}) -> #'RSAPublicKey'{modulus = Mod, publicExponent = Exp}. +remote_sign_request(URL, Request) -> + case plop_httputil:request("signing", URL, [{"Content-Type", "text/json"}], list_to_binary(mochijson2:encode(Request))) of + {failure, StatusLine, RespHeaders, Body} -> + lager:debug("auth check failed"), + none; + {success, StatusLine, RespHeaders, Body} -> + lager:debug("auth check succeeded"), + case (catch mochijson2:decode(Body)) of + {error, E} -> + none; + {struct, PropList} -> + base64:decode(proplists:get_value(<<"result">>, PropList)) + end; + {noauth, StatusLine, RespHeaders, Body} -> + lager:debug("no auth"), + none + end. + %%%%%%%%%%%%%%%%%%%% %% Public API. -sign(Data) -> - call(?MODULE, {sign, Data}). +sign_sct(Data = <<_Version:8, + ?CERTIFICATE_TIMESTAMP:8, + _/binary>>) -> + case application:get_env(plop, signing_node) of + {ok, URLBase} -> + Request = {[{plop_version, 1}, + {data, base64:encode(Data)} + ]}, + remote_sign_request(URLBase ++ "sct", Request); + undefined -> + call(?MODULE, {sign, Data}) + end. + +sign_sth(Data = <<_Version:8, + ?TREE_HASH:8, + _/binary>>) -> + case application:get_env(plop, signing_node) of + {ok, URLBase} -> + Request = {[{plop_version, 1}, + {data, base64:encode(Data)} + ]}, + remote_sign_request(URLBase ++ "sth", Request); + undefined -> + call(?MODULE, {sign, Data}) + end. get_pubkey() -> call(?MODULE, {get, pubkey}). get_logid() -> - call(?MODULE, {get, logid}). + PubKeyfile = application:get_env(plop, log_public_key, none), + read_keyfile_ec_logid(PubKeyfile). %%%%%%%%%%%%%%%%%%%% %% gen_server callbacks. diff --git a/src/signing.erl b/src/signing.erl new file mode 100644 index 0000000..707b18e --- /dev/null +++ b/src/signing.erl @@ -0,0 +1,42 @@ +%%% Copyright (c) 2014, NORDUnet A/S. +%%% See LICENSE for licensing information. + +%%% @doc Signing node API + +-module(signing). +%% API (URL) +-export([request/3]). + +request(post, "ct/signing/sct", Input) -> + case (catch mochijson2:decode(Input)) of + {error, E} -> + html("sendentry: bad input:", E); + {struct, PropList} -> + Data = base64:decode(proplists:get_value(<<"data">>, PropList)), + + Result = sign:sign_sct(Data), + success({[{result, base64:encode(Result)}]}) + end; +request(post, "ct/signing/sth", Input) -> + case (catch mochijson2:decode(Input)) of + {error, E} -> + html("sendentry: bad input:", E); + {struct, PropList} -> + Data = base64:decode(proplists:get_value(<<"data">>, PropList)), + + Result = sign:sign_sth(Data), + success({[{result, base64:encode(Result)}]}) + end. + +%% Private functions. +html(Text, Input) -> + {400, [{"Content-Type", "text/html"}], + io_lib:format( + "

~n" ++ + "~s~n" ++ + "~p~n" ++ + "~n", [Text, Input])}. + +success(Data) -> + lager:debug("returning ~p", [Data]), + {200, [{"Content-Type", "text/json"}], mochijson2:encode(Data)}. -- cgit v1.1