change taler-exchange-sepa to a more generic taler-exchange-wire tool using the wire plugins (#4237)

This commit is contained in:
Christian Grothoff 2016-04-02 20:58:22 +02:00
parent 937078bbdc
commit daae3d3ddf
11 changed files with 499 additions and 260 deletions

View File

@ -10,6 +10,7 @@ man_MANS = \
taler-exchange-keyup.1 \
taler-exchange-keycheck.1 \
taler-exchange-reservemod.1 \
taler-exchange-wire.1 \
taler.conf.5
EXTRA_DIST = \

View File

@ -1,41 +0,0 @@
.TH TALER\-EXCHANGE\-SEPA 1 "Apr 22, 2015" "GNU Taler"
.SH NAME
taler\-exchange\-sepa \- Create the master-key signed response to /wire/sepa.
.SH SYNOPSIS
.B taler\-exchange\-sepa
.RI [ options ]
.br
.SH DESCRIPTION
\fBtaler\-exchange\-sepa\fP is used to create the exchange's reply to a /wire/sepa request. It converts the bank details into the appropriate signed response. This needs to be done using the long-term offline master key.
.SH OPTIONS
.B
.IP "\-b BIC, \-\-bic=BIC"
Specifies the BIC code to use.
.B
.IP "\-i IBAN, \-\-iban=IBAN"
Specifies the IBAN to use.
.B
.IP "\-n NAME, \-\-name=NAME"
Specifies the name of the account holder.
.B
.IP "\-m MASTERKEYFILE, \-\-master=MASTERKEYFILE"
Specifies the name of the file containing the exchange's master key.
.B
.IP "\-o FILENAME, \-\-output=FILENAME"
Where to write the SEPA_RESPONSE_FILE.
.B
.IP "\-h, \-\-help"
Print short help on options.
.B
.IP "\-v, \-\-version"
Print version information.
.SH BUGS
Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <taler@gnu.org>
.SH "SEE ALSO"
\fBtaler\-exchange\-httpd\fP(1), \fBtaler.conf\fP(5)

38
doc/taler-exchange-wire.1 Normal file
View File

@ -0,0 +1,38 @@
.TH TALER\-EXCHANGE\-WIRE 1 "Apr 2, 2016" "GNU Taler"
.SH NAME
taler\-exchange\-wire \- Create the master-key signed responses to /wire.
.SH SYNOPSIS
.B taler\-exchange\-wire
.RI [ options ]
.br
.SH DESCRIPTION
\fBtaler\-exchange\-wire\fP is used to create the exchange's reply to a /wire request. It converts the bank details into the appropriate signed response. This needs to be done using the long-term offline master key.
.SH OPTIONS
.B
.IP "\-j JSON, \-\-json=JSON"
Gives JSON with all of the relevant account details in a method-specific format.
.B
.IP "\-t METHOD, \-\-type=METHOD"
Specifies the wire transfer method to use. Common are 'test' and 'sepa'.
.B
.IP "\-m MASTERKEYFILE, \-\-master=MASTERKEYFILE"
Specifies the name of the file containing the exchange's master key.
.B
.IP "\-o FILENAME, \-\-output=FILENAME"
Where to write the SEPA_RESPONSE_FILE.
.B
.IP "\-h, \-\-help"
Print short help on options.
.B
.IP "\-v, \-\-version"
Print version information.
.SH BUGS
Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <taler@gnu.org>
.SH "SEE ALSO"
\fBtaler\-exchange\-httpd\fP(1), \fBtaler.conf\fP(5)

View File

@ -11,7 +11,7 @@ bin_PROGRAMS = \
taler-exchange-keyup \
taler-exchange-keycheck \
taler-exchange-reservemod \
taler-exchange-sepa \
taler-exchange-wire \
taler-exchange-dbinit
taler_exchange_keyup_SOURCES = \
@ -33,15 +33,15 @@ taler_auditor_sign_LDADD = \
-lgnunetutil $(XLIB)
taler_exchange_sepa_SOURCES = \
taler-exchange-sepa.c
taler_exchange_sepa_LDADD = \
taler_exchange_wire_SOURCES = \
taler-exchange-wire.c
taler_exchange_wire_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
-lgnunetjson \
-lgnunetutil \
-ljansson $(XLIB)
taler_exchange_sepa_LDFLAGS = $(POSTGRESQL_LDFLAGS)
taler_exchange_wire_LDFLAGS = $(POSTGRESQL_LDFLAGS)
taler_exchange_keycheck_SOURCES = \
taler-exchange-keycheck.c

View File

@ -1,189 +0,0 @@
/*
This file is part of TALER
Copyright (C) 2015 GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file taler-exchange-sepa.c
* @brief Create signed response for /wire/sepa requests.
* @author Christian Grothoff
*/
#include <platform.h>
#include <jansson.h>
#include <gnunet/gnunet_json_lib.h>
#include "taler_crypto_lib.h"
#include "taler_signatures.h"
/**
* Filename of the master private key.
*/
static char *masterkeyfile;
/**
* Account holder name.
*/
static char *sepa_name;
/**
* Account holder address.
*/
static char *sepa_address;
/**
* IBAN number.
*/
static char *iban;
/**
* BIC number.
*/
static char *bic;
/**
* Where to write the result.
*/
static char *output_filename;
/**
* The main function of the taler-exchange-sepa tool. This tool is used
* to sign the SEPA bank account details using the master key.
*
* @param argc number of arguments from the command line
* @param argv command line arguments
* @return 0 ok, 1 on error
*/
int
main (int argc,
char *const *argv)
{
static const struct GNUNET_GETOPT_CommandLineOption options[] = {
{'a', "address", "ADDRESS",
"account holder address", 1,
&GNUNET_GETOPT_set_string, &sepa_address},
{'b', "bic", "BICCODE",
"bank BIC code", 1,
&GNUNET_GETOPT_set_string, &bic},
{'i', "iban", "IBAN",
"IBAN number of the account", 1,
&GNUNET_GETOPT_set_string, &iban},
{'m', "master-key", "FILE",
"master key file (private key)", 1,
&GNUNET_GETOPT_set_filename, &masterkeyfile},
{'n', "name", "NAME",
"name of the account holder", 1,
&GNUNET_GETOPT_set_string, &sepa_name},
{'o', "output", "FILE",
"where to write the result", 1,
&GNUNET_GETOPT_set_filename, &output_filename},
TALER_GETOPT_OPTION_HELP ("Setup /wire/sepa response"),
GNUNET_GETOPT_OPTION_VERSION (VERSION "-" VCS_VERSION),
GNUNET_GETOPT_OPTION_END
};
struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_priv;
struct TALER_MasterWireSepaDetailsPS wsd;
struct TALER_MasterSignatureP sig;
struct GNUNET_HashContext *hc;
json_t *reply;
char *json_str;
struct GNUNET_HashCode salt;
GNUNET_assert (GNUNET_OK ==
GNUNET_log_setup ("taler-exchange-sepa",
"WARNING",
NULL));
if (GNUNET_GETOPT_run ("taler-exchange-sepa",
options,
argc, argv) < 0)
return 1;
if (NULL == masterkeyfile)
{
fprintf (stderr,
"Master key file not given\n");
return 1;
}
eddsa_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile);
if (NULL == eddsa_priv)
{
fprintf (stderr,
"Failed to initialize master key from file `%s'\n",
masterkeyfile);
return 1;
}
if ( (NULL == sepa_address) ||
(NULL == iban) ||
(NULL == sepa_name) ||
(NULL == bic) )
{
fprintf (stderr,
"Required arguments missing\n");
return 1;
}
/* Compute message to sign */
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&salt,
sizeof (salt));
hc = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hc,
sepa_name,
strlen (sepa_name) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
iban,
strlen (iban) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
bic,
strlen (bic) + 1);
wsd.purpose.size = htonl (sizeof (wsd));
wsd.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
GNUNET_CRYPTO_hash_context_finish (hc,
&wsd.h_sepa_details);
GNUNET_CRYPTO_eddsa_sign (eddsa_priv,
&wsd.purpose,
&sig.eddsa_signature);
GNUNET_free (eddsa_priv);
/* build JSON message */
reply = json_pack ("{s:s, s:s, s:s, s:s, s:s, s:o, s:o}",
"type", "sepa",
"address", sepa_address,
"receiver_name", sepa_name,
"iban", iban,
"bic", bic,
"salt", GNUNET_JSON_from_data (&salt,
sizeof (salt)),
"sig", GNUNET_JSON_from_data (&sig,
sizeof (sig)));
GNUNET_assert (NULL != reply);
/* dump result to stdout */
json_str = json_dumps (reply, JSON_INDENT(2));
GNUNET_assert (NULL != json_str);
if (NULL != output_filename)
{
fclose (stdout);
stdout = fopen (output_filename,
"w+");
}
fprintf (stdout,
"%s",
json_str);
fflush (stdout);
free (json_str);
return 0;
}
/* end of taler-exchange-sepa.c */

View File

@ -0,0 +1,201 @@
/*
This file is part of TALER
Copyright (C) 2015, 2016 Inria
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file taler-exchange-wire.c
* @brief Create signed response for /wire requests.
* @author Christian Grothoff
*/
#include <platform.h>
#include <jansson.h>
#include <gnunet/gnunet_json_lib.h>
#include "taler_crypto_lib.h"
#include "taler_wire_plugin.h"
#include "taler_signatures.h"
/**
* Filename of the master private key.
*/
static char *masterkeyfile;
/**
* Account holder information in JSON format.
*/
static char *json_in;
/**
* Which wire method is this for?
*/
static char *method;
/**
* Where to write the result.
*/
static char *output_filename;
/**
* The main function of the taler-exchange-sepa tool. This tool is used
* to sign the SEPA bank account details using the master key.
*
* @param argc number of arguments from the command line
* @param argv command line arguments
* @return 0 ok, 1 on error
*/
int
main (int argc,
char *const *argv)
{
static const struct GNUNET_GETOPT_CommandLineOption options[] = {
{'j', "json", "JSON",
"account information in JSON format", 1,
&GNUNET_GETOPT_set_string, &json_in},
{'m', "master-key", "FILE",
"master key file (private key)", 1,
&GNUNET_GETOPT_set_filename, &masterkeyfile},
{'t', "type", "METHOD",
"which wire transfer method (i.e. 'test' or 'sepa') is this for?", 1,
&GNUNET_GETOPT_set_filename, &method},
{'o', "output", "FILE",
"where to write the result", 1,
&GNUNET_GETOPT_set_filename, &output_filename},
TALER_GETOPT_OPTION_HELP ("Setup /wire response"),
GNUNET_GETOPT_OPTION_VERSION (VERSION "-" VCS_VERSION),
GNUNET_GETOPT_OPTION_END
};
struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_priv;
struct TALER_MasterPrivateKeyP key;
struct TALER_MasterSignatureP sig;
json_t *j;
json_error_t err;
char *json_out;
struct GNUNET_HashCode salt;
char *lib_name;
struct TALER_WIRE_Plugin *plugin;
GNUNET_assert (GNUNET_OK ==
GNUNET_log_setup ("taler-exchange-wire",
"WARNING",
NULL));
if (GNUNET_GETOPT_run ("taler-exchange-wire",
options,
argc, argv) < 0)
return 1;
if (NULL == masterkeyfile)
{
fprintf (stderr,
"Master key file not given\n");
return 1;
}
eddsa_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile);
if (NULL == eddsa_priv)
{
fprintf (stderr,
"Failed to initialize master key from file `%s'\n",
masterkeyfile);
return 1;
}
if (NULL == json_in)
{
fprintf (stderr,
"Required -j argument missing\n");
return 1;
}
if (NULL == method)
{
fprintf (stderr,
"Required -t argument missing\n");
return 1;
}
j = json_loads (json_in,
JSON_REJECT_DUPLICATES,
&err);
if (NULL == j)
{
fprintf (stderr,
"Failed to parse JSON: %s (at offset %u)\n",
err.text,
(unsigned int) err.position);
return 1;
}
key.eddsa_priv = *eddsa_priv;
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&salt,
sizeof (salt));
(void) GNUNET_asprintf (&lib_name,
"libtaler_plugin_wire_%s",
method);
plugin = GNUNET_PLUGIN_load (lib_name,
NULL);
if (NULL == plugin)
{
GNUNET_free (lib_name);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Wire transfer method `%s' not supported\n",
method);
return 1;
}
plugin->library_name = lib_name;
if (GNUNET_OK !=
plugin->sign_wire_details (plugin->cls,
j,
&key,
&salt,
&sig))
{
/* sign function should have logged applicable errors */
json_decref (j);
GNUNET_PLUGIN_unload (lib_name,
plugin);
GNUNET_free (lib_name);
return 1;
}
GNUNET_PLUGIN_unload (lib_name,
plugin);
GNUNET_free (lib_name);
GNUNET_free (eddsa_priv);
/* add signature and salt to JSON message */
json_object_set_new (j,
"salt",
GNUNET_JSON_from_data (&salt,
sizeof (salt)));
json_object_set_new (j,
"sig",
GNUNET_JSON_from_data (&sig,
sizeof (sig)));
/* dump result to stdout */
json_out = json_dumps (j, JSON_INDENT(2));
json_decref (j);
GNUNET_assert (NULL != json_out);
if (NULL != output_filename)
{
fclose (stdout);
stdout = fopen (output_filename,
"w+");
}
fprintf (stdout,
"%s",
json_out);
fflush (stdout);
free (json_out);
return 0;
}
/* end of taler-exchange-wire.c */

View File

@ -69,10 +69,16 @@
/**
* Signature where the Exchange confirms its SEPA details in
* the /wire/sepa response.
* the /wire response.
*/
#define TALER_SIGNATURE_MASTER_SEPA_DETAILS 1026
/**
* Signature where the Exchange confirms its TEST details in
* the /wire response.
*/
#define TALER_SIGNATURE_MASTER_TEST_DETAILS 1027
/*********************************************/
/* Exchange online signatures (with signing key) */
@ -762,11 +768,12 @@ struct TALER_RefreshCommitLinkP
* @brief Information signed by the exchange's master
* key affirming the SEPA details for the exchange.
*/
struct TALER_MasterWireSepaDetailsPS
struct TALER_MasterWireDetailsPS
{
/**
* Purpose is #TALER_SIGNATURE_MASTER_SEPA_DETAILS.
* Purpose is #TALER_SIGNATURE_MASTER_SEPA_DETAILS or
* #TALER_SIGNATURE_MASTER_TEST_DETAILS.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;

View File

@ -113,6 +113,24 @@ struct TALER_WIRE_Plugin
const char *account_name);
/**
* Sign wire transfer details in the plugin-specific format.
*
* @param cls closure
* @param in wire transfer details in JSON format
* @param key private signing key to use
* @param salt salt to add
* @param[out] sig where to write the signature
* @return #GNUNET_OK on success
*/
int
(*sign_wire_details)(void *cls,
const json_t *in,
const struct TALER_MasterPrivateKeyP *key,
const struct GNUNET_HashCode *salt,
struct TALER_MasterSignatureP *sig);
/**
* Check if the given wire format JSON object is correctly formatted
*

View File

@ -351,6 +351,42 @@ validate_iban (const char *iban)
}
/**
* Compute purpose for signing.
*
* @param sepa_name name of the account holder
* @param iban bank account number in IBAN format
* @param bic bank identifier
* @param[out] mp purpose to be signed
*/
static void
compute_purpose (const char *sepa_name,
const char *iban,
const char *bic,
struct TALER_MasterWireDetailsPS *wsd)
{
struct GNUNET_HashContext *hc;
wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
hc = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hc,
"sepa",
strlen ("sepa") + 1);
GNUNET_CRYPTO_hash_context_read (hc,
sepa_name,
strlen (sepa_name) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
iban,
strlen (iban) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
bic,
strlen (bic) + 1);
GNUNET_CRYPTO_hash_context_finish (hc,
&wsd->h_sepa_details);
}
/**
* Verify that the signature in the @a json for /wire/sepa is valid.
*
@ -365,14 +401,13 @@ verify_wire_sepa_signature_ok (const json_t *json,
const struct TALER_MasterPublicKeyP *master_pub)
{
struct TALER_MasterSignatureP exchange_sig;
struct TALER_MasterWireSepaDetailsPS mp;
const char *receiver_name;
struct TALER_MasterWireDetailsPS mp;
const char *name;
const char *iban;
const char *bic;
struct GNUNET_HashContext *hc;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("sig", &exchange_sig),
GNUNET_JSON_spec_string ("receiver_name", &receiver_name),
GNUNET_JSON_spec_string ("name", &name),
GNUNET_JSON_spec_string ("iban", &iban),
GNUNET_JSON_spec_string ("bic", &bic),
GNUNET_JSON_spec_end()
@ -391,22 +426,10 @@ verify_wire_sepa_signature_ok (const json_t *json,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
mp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
mp.purpose.size = htonl (sizeof (struct TALER_MasterWireSepaDetailsPS));
hc = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hc,
receiver_name,
strlen (receiver_name) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
iban,
strlen (iban) + 1);
GNUNET_CRYPTO_hash_context_read (hc,
bic,
strlen (bic) + 1);
GNUNET_CRYPTO_hash_context_finish (hc,
&mp.h_sepa_details);
compute_purpose (name,
iban,
bic,
&mp);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS,
&mp.purpose,
@ -447,12 +470,12 @@ sepa_wire_validate (void *cls,
"{"
"s:s," /* type: sepa */
"s:s," /* iban: IBAN */
"s:s," /* receiver_name: beneficiary name */
"s:s," /* name: beneficiary name */
"s:s" /* bic: beneficiary bank's BIC */
"}",
"type", &type,
"iban", &iban,
"receiver_name", &name,
"name", &name,
"bic", &bic))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@ -548,6 +571,70 @@ sepa_get_wire_details (void *cls,
}
/**
* Sign wire transfer details in the plugin-specific format.
*
* @param cls closure
* @param in wire transfer details in JSON format
* @param key private signing key to use
* @param salt salt to add
* @param[out] sig where to write the signature
* @return #GNUNET_OK on success
*/
static int
sepa_sign_wire_details (void *cls,
const json_t *in,
const struct TALER_MasterPrivateKeyP *key,
const struct GNUNET_HashCode *salt,
struct TALER_MasterSignatureP *sig)
{
struct TALER_MasterWireDetailsPS wsd;
const char *sepa_name;
const char *iban;
const char *bic;
const char *type;
json_error_t err;
if (0 !=
json_unpack_ex ((json_t *) in,
&err,
0 /* flags */,
"{s:s, s:s, s:s, s:s}",
"type", &type,
"name", &sepa_name,
"iban", &iban,
"bic", &bic))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to unpack JSON: %s (at %u)\n",
err.text,
err.position);
return GNUNET_SYSERR;
}
if (0 != strcmp (type,
"sepa"))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"`type' must be `sepa' for SEPA wire details\n");
return GNUNET_SYSERR;
}
if (1 != validate_iban (iban))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"IBAN invalid in SEPA wire details\n");
return GNUNET_SYSERR;
}
compute_purpose (sepa_name,
iban,
bic,
&wsd);
GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
&wsd.purpose,
&sig->eddsa_signature);
return GNUNET_OK;
}
/**
* Prepare for exeuction of a wire transfer.
*
@ -662,6 +749,7 @@ libtaler_plugin_wire_sepa_init (void *cls)
plugin->cls = sc;
plugin->amount_round = &sepa_amount_round;
plugin->get_wire_details = &sepa_get_wire_details;
plugin->sign_wire_details = &sepa_sign_wire_details;
plugin->wire_validate = &sepa_wire_validate;
plugin->prepare_wire_transfer = &sepa_prepare_wire_transfer;
plugin->prepare_wire_transfer_cancel = &sepa_prepare_wire_transfer_cancel;

View File

@ -171,6 +171,28 @@ template_execute_wire_transfer (void *cls,
}
/**
* Sign wire transfer details in the plugin-specific format.
*
* @param cls closure
* @param in wire transfer details in JSON format
* @param key private signing key to use
* @param salt salt to add
* @param[out] sig where to write the signature
* @return #GNUNET_OK on success
*/
static int
template_sign_wire_details (void *cls,
const json_t *in,
const struct TALER_MasterPrivateKeyP *key,
const struct GNUNET_HashCode *salt,
struct TALER_MasterSignatureP *sig)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
/**
* Abort execution of a wire transfer. For example, because we are
* shutting down. Note that if an execution is aborted, it may or
@ -236,6 +258,7 @@ libtaler_plugin_wire_template_init (void *cls)
plugin->cls = tc;
plugin->amount_round = &template_amount_round;
plugin->get_wire_details = &template_get_wire_details;
plugin->sign_wire_details = &template_sign_wire_details;
plugin->wire_validate = &template_wire_validate;
plugin->prepare_wire_transfer = &template_prepare_wire_transfer;
plugin->prepare_wire_transfer_cancel = &template_prepare_wire_transfer_cancel;

View File

@ -22,6 +22,7 @@
#include "platform.h"
#include "taler_wire_plugin.h"
#include "taler_bank_service.h"
#include "taler_signatures.h"
/* only for HTTP status codes */
#include <microhttpd.h>
@ -285,6 +286,38 @@ test_get_wire_details (void *cls,
}
/**
* Compute purpose for signing.
*
* @param account number of the account
* @param bank_uri URI of the bank
* @param[out] mp purpose to be signed
*/
static void
compute_purpose (uint64_t account,
const char *bank_uri,
struct TALER_MasterWireDetailsPS *wsd)
{
struct GNUNET_HashContext *hc;
uint64_t n = GNUNET_htonll (account);
wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_TEST_DETAILS);
hc = GNUNET_CRYPTO_hash_context_start ();
GNUNET_CRYPTO_hash_context_read (hc,
"test",
strlen ("test") + 1);
GNUNET_CRYPTO_hash_context_read (hc,
&n,
sizeof (n));
GNUNET_CRYPTO_hash_context_read (hc,
bank_uri,
strlen (bank_uri) + 1);
GNUNET_CRYPTO_hash_context_finish (hc,
&wsd->h_sepa_details);
}
/**
* Check if the given wire format JSON object is correctly formatted.
* Right now, the only thing we require is a field
@ -319,6 +352,10 @@ test_wire_validate (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
/* FIXME: should check signature here in the future!
(note: right now the sig is not properly provided
by the exchange due to the way account data is
specified in the configuration) */
return GNUNET_YES;
}
@ -510,6 +547,61 @@ execute_cb (void *cls,
}
/**
* Sign wire transfer details in the plugin-specific format.
*
* @param cls closure
* @param in wire transfer details in JSON format
* @param key private signing key to use
* @param salt salt to add
* @param[out] sig where to write the signature
* @return #GNUNET_OK on success
*/
static int
test_sign_wire_details (void *cls,
const json_t *in,
const struct TALER_MasterPrivateKeyP *key,
const struct GNUNET_HashCode *salt,
struct TALER_MasterSignatureP *sig)
{
struct TALER_MasterWireDetailsPS wsd;
const char *bank_uri;
const char *type;
json_int_t account;
json_error_t err;
if (0 !=
json_unpack_ex ((json_t *) in,
&err,
0 /* flags */,
"{s:s, s:s, s:I}",
"type", &type,
"bank_uri", &bank_uri,
"account_number", &account))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to unpack JSON: %s (at %u)\n",
err.text,
err.position);
return GNUNET_SYSERR;
}
if (0 != strcmp (type,
"test"))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"`type' must be `test' for test wire details\n");
return GNUNET_SYSERR;
}
compute_purpose (account,
bank_uri,
&wsd);
GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
&wsd.purpose,
&sig->eddsa_signature);
return GNUNET_OK;
}
/**
* Execute a wire transfer.
*
@ -682,6 +774,7 @@ libtaler_plugin_wire_test_init (void *cls)
plugin->cls = tc;
plugin->amount_round = &test_amount_round;
plugin->get_wire_details = &test_get_wire_details;
plugin->sign_wire_details = &test_sign_wire_details;
plugin->wire_validate = &test_wire_validate;
plugin->prepare_wire_transfer = &test_prepare_wire_transfer;
plugin->prepare_wire_transfer_cancel = &test_prepare_wire_transfer_cancel;