TALER-EXCHANGE-OFFLINE(1)

NAME
taler-exchange-offline - operations using the offline key of a Taler exchange

SYNOPSIS

taler-exchange-offline [-c FILENAME | --config=‌FILENAME] [-h | --help] [-L LOGLEVEL | --loglevel=‌LOGLEVEL] [-l FILENAME | --logfile=‌FILENAME] [-v | --version] [subcommand ...]

DESCRIPTION

taler-exchange-offline is a command-line tool to interact with the Taler exchange's master private key. Most operations of this tool require access to the exchange’s long-term offline signing key and should be run in a secure (offline) environment under strict controls. The tool takes a list of subcommands as arguments which are then processed sequentially.

The tool includes two subcommands to interact online with the exchange's REST APIs. To determine how to talk to the exchange, these two subcommands rely on the BASE_URL configuration option from the [exchange] section of the configuration file. The download subcommand downloads the future public keys from the running exchange. The resulting data serves as input to the sign and show subcommands. The upload subcommand uploads the signatures created with the private master key to the exchange. It handles the output of all subcommands (except download). The download and upload subcommands must naturally be run "online" and do not require access to the offline key.

All other subcommands are intended to be run "offline". However, especially when testing, it is of course possible to run the subcommands online as well. Generally, subcommands read inputs (beyond command-line arguments) from stdin. However, they may also consume outputs of previous subcommands. The outputs of multiple subcommands are automatically combined, and if not consumed the final output is printed to stdout.

The general options for taler-exchange-offline are:

-c FILENAME | --config=‌FILENAME
    Use the configuration and other resources for the merchant to operate from FILENAME.

-h | --help
    Print short help on options.

-L LOGLEVEL | --loglevel=‌LOGLEVEL
    Specifies the log level to use. Accepted values are: DEBUG, INFO, WARNING, ERROR.

-l FILENAME | --logfile=‌FILENAME
    Send logging output to FILENAME.

-v | --version
    Print version information.

CONFIGURATION

The exchange validates all operations by checking the signatures against the master public key that must be provided in the exchange configuration. To obtain the master public key, use:

    $ taler-exchange-offline setup

Note that if the private key file already exists, the above will simply output the existing key. Passing additional arguments after setup (including "-") will cause the output to be encapsulated in JSON.

Relevant configuration options for taler-exchange-offline are:

•   [exchange/BASE_URL] --- how to reach the exchange (for download/upload)

•   [exchange-offline/MASTER_PRIV_FILE] --- where to store the private keys

•   [exchange-offline/SECM_TOFU_FILE] --- where to store TOFU data

SUBCOMMANDS

  setup

When run the first time, this subcommand sets up the offline private key and outputs the resulting public key. Subsequent invocations will simply again output the (same) public key (in the format usable for the exchange configuration).

  download

This subcommand must be run online. It downloads future signing and denomination keys with the associated meta data from the exchange and outputs the resulting JSON (for consumption by subsequent subcommands, or to stdout).

  show

This subcommand outputs information about future signing and denomination keys for manual checking against the business-approved fee structure, lifetimes and other parameters.

It consumes the output of the download subcommand, either from stdin or directly. However, if given arg - (hyphen), this input is not consumed, but instead is passed to the next command. This functions like the tee(1) command.

Its output always goes to stdout for human consumption (not in JSON). It is usually a bad idea (but possible) to combine show with other subcommands, except maybe for testing.

  sign

This subcommand signs information about future signing and denomination keys.

It consumes the output of the download subcommand, either from stdin or directly.

It outputs the signatures over all denomination and signing keys present in the input, in a format suitable for the upload subcommand.

  extensions

This subcommand is responsible for the management of available extensions in the exchange.

It consumes the output of the download subcommand, either from stdin or directly.

It provides the sub-subcommand extensions show to show the configuration for extensions and the extensions sign command to sign the current configuration of extensions, in a format suitable for the upload subcommand.

Note that an extension on the exchange will only become activated at runtime after the extension's configurations has been signed by the offline tool with the signing key and the signed configuration been uploaded to the exchange.

  drain

This subcommand allows an exchange operator to transfer the profits made from transaction fees to a regular (non-escrowed) bank account. Using this command, draining profits from the escrow account can be done in such a way that the auditor is aware of the special transaction and does not flag the resulting balance as fundamentally problematic. Note that the drained amounts must still total up to less than the fees earned by the exchange.

Arguments to the drain command are the amount to be drained (in the usual Taler amount format), the section of the exchange configuration specifying the account to be debited (this argument is currently ignored, and the account is purely derived from the wire method and the account being set for debiting), and finally the payto://-URI to wire the funds to.

Note that to actually wire the funds, the exchange administrator must run taler-exchange-drain manually and confirm the operation after the upload was completed.

  revoke-denomination

This subcommand signs a revocation message for a denomination key.

The hash of the denomination public key must be given in the usual base32-encoding as the first and only argument to the subcommand.

It outputs the signature affirming the revocation of the denomination key, in a format suitable for the upload subcommand.

  revoke-signkey

This subcommand signs a revocation message for an exchange online signing key.

The online signing public key must be given in the usual base32-encoding as the first and only argument to the subcommand.

It outputs the signature affirming the revocation of the online signing key, in a format suitable for the upload subcommand.

  enable-auditor

This subcommand informs an exchange that an auditor is to be activated. Afterwards, the exchange will accept inputs from that auditor's taler-auditor-offline tool. The exchange's database will need to be provided to the auditor. This subcommand only informs the exchange about the auditor, but does not perform those additional mandatory steps for a working auditor.

The auditor's public key must be given in the usual base32-encoding as the first argument.

The auditor's REST API base URL must be given as the second argument. The tool performs a minimal sanity check, namely that the URL begins with "http" (this also allows "https"), but as it runs offline does not perform any further validation!

The third argument must be a human-readable name for the auditor. This may be shown to users and should identify the auditor's business entity. If the name includes spaces, the argument should be quoted.

The subcommand takes no inputs from stdin or other subcommands.

It outputs the signature affirming the addition of the auditor, in a format suitable for the upload subcommand.

  disable-auditor

This subcommand informs an exchange that an auditor is to be deactivated. Afterwards, the exchange will refuse inputs from that auditor's taler-auditor-offline tool.

The auditor's public key must be given in the usual base32-encoding as the first argument.

The subcommand takes no inputs from stdin or other subcommands.

It outputs the signature affirming the removal of the auditor, in a format suitable for the upload subcommand.

  enable-account

This subcommand informs an exchange that it should advertise a bank account as belonging to the exchange on its /keys endpoint. Note that this does not ensure that the exchange will use this bank account for incoming or outgoing wire transfers! For this, the taler-exchange-transfer and taler-exchange-wirewatch tools must be configured. Furthermore, the bank account information advertised could theoretically differ from that which these tool actually use, for example if the public bank account is only a front for the actual internal business accounts.

The payto:// URI (RFC 8905) of the exchange's bank account must be given as the first argument to the subcommand.

Afterwards, optional arguments can be given:

•   conversion-url $URL: specifies that using this bank account is subject to currency conversion. $URL must be the address of a currency conversion REST API that allows merchants and wallets to determine the current conversion rate.

•   display-hint $PRIORITY $LABEL: specifies that this bank account should be shown to the user with the given numeric $PRIORITY (higher is earlier, zero is hidden for manual withdrawal) and with the given $LABEL. This is useful to ensure that if an exchange has multiple bank accounts, we can show the user those that are most likely useful first, and give them appropriately labeled hints for selecting other accounts as well. A display hint is optional, if missing the priority is 1 and the wallet must pick some appropriate label itself somehow.

•   credit-restriction $TYPE [$ARGS]: Specifies that there are restrictions in place when crediting this bank account. Details depend on the restriction $TYPE. This argument may be given multiple times, in which case debitor accounts must satisfy all restrictions. Restriction types are discussed below.

•   debit-restriction $TYPE [$ARGS]: Specifies that there are restrictions in place when receiving money from the exchange. Wallets and merchants must check that their target bank account satisfies these restrictions before sending deposit requests to the exchange. Details depend on the restriction $TYPE. This argument may be given multiple times, in which case debitor accounts must satisfy all restrictions. Restriction types are discussed below.

    The following types of credit- and debit-restrictions are supported:

•   deny: A $TYPE of deny means that this bank account cannot be used for the given operation. deny takes no further arguments.

•   regex $EXPR $HINT $JSON: A $TYPE of regex means that the partner's bank account payto-URI representation must follow a certain regular expression given in $EXPR where the syntax follows posix-egrep, but without support for character classes, GNU extensions, back-references or intervals. See Findutils Manual for a description of the posix-egrep syntax. The $HINT must be a human-readable description of the $EXPR. $JSON should be a JSON array mapping IETF BCP 47 language tags to localized versions of $HINT.

    The subcommand takes no inputs from stdin or other subcommands.

    It outputs the signature affirming the addition of the wire account, in a format suitable for the upload subcommand.

  disable-account

This subcommand informs an exchange that it should stop advertising a bank account as belonging to the exchange on its /keys endpoint.

The payto:// URI (RFC 8905) of the exchange's (former) bank account must be given as the first argument to the subcommand.

The subcommand takes no inputs from stdin or other subcommands.

It outputs the signature affirming the deletion of the wire account, in a format suitable for the upload subcommand.

  wire-fee

This subcommand informs an exchange about the desired wire fee structure (that is, wire, and closing fees) for particular wire method and a calendar year (!). The tool does not permit changing wire fees during a calendar year. Also, once the wire fee has been set for a calendar year, it cannot be changed.

The subcommand takes the year, wire-method (see RFC 8905, examples include x-taler-bank or iban), wire fee, and closing fee as arguments. Instead of a year, the string now can be given for the current year (this is mostly useful for test cases). The wire-method should follow the GANA registry as given in RFC 8905. The fees must be given in the usual Taler format of CURRENCY:NUMBER.FRACTION.

The subcommand takes no inputs from stdin or other subcommands.

It outputs the signature affirming the wire fees, in a format suitable for the upload subcommand.

  global-fee

This subcommand informs an exchange about the desired global fee structure and related global configuration options for a calendar year (!). The tool does not permit changing global fees during a calendar year. Also, once the global fee structure has been set for a calendar year, it cannot be changed.

The subcommand takes the year, history fee, account fee, purse fee, purse timeout, history expiration and the (free) purse (per) account limit as arguments. Instead of a year, the string now can be given for the current year (this is mostly useful for test cases). The fees must be given in the usual Taler format of CURRENCY:NUMBER.FRACTION.

The arguments provided must include:

1.  Calendar year for which the fee applies, 'now' for the current year.

2.  History fee charged when inquiring about non-recent account history (not implemented, use zero!)

3.  Account fee charged for opening an account (not supported by wallet, use zero!)

4.  Purse fee. How much will the exchange charge for an abandoned purse. Also the minimum amount that can be in a purse that is not associated with an account. (Not well supported by wallets, use zero!)

5.  Purse timeout. How long does the exchange keep information about a purse around after it expired or was successfully merged?

6.  How long will the exchange preserve an account history.

7.  Number of free purses per account. (Irrelevant if purse fee is zero).

    The subcommand takes no inputs from stdin or other subcommands.

    It outputs the signature affirming the global fees, in a format suitable for the upload subcommand.

  enable-partner

This subcommand informs an exchange about the wad fee and frequency to apply to a partner exchange. The arguments provided must include:

1.  Partner exchange base URL.

2.  Partner exchange master public key.

3.  Calendar year for which the fee applies, 'now' for the current year.

4.  Wad frequency, in minutes (for example, '30').

5.  Wad fee (for example, 'KUDOS:0.1').

  aml-enable

Enable AML officer's account, granting them access to AML data and, if 'rw' is given, the power to make AML decisions.

The arguments provided must include:

1.  AML staff member public key (in base32 encoding)

2.  AML staff member legal name

3.  'ro' or 'rw' to set access to read-only or read-write

  aml-disable

Disable AML officer's account. Also updates the legal name.

The arguments provided must include:

1.  AML staff member public key (in base32 encoding)

2.  AML staff member legal name

  add-partner

Add partner exchange for wad transfers. Enables P2P payments between users of these exchanges.

The arguments provided must include:

1.  Master public key of the partner exchange.

2.  Base URL of the partner exchange API.

3.  Wad fee to charge.

4.  Wad transfer frequency.

5.  Year for which the above options are to be configured, 'now' for the current year.

  upload

This subcommand uploads outputs from other subcommands (except download and show) to the exchange. Note that it is possible that some uploads succeed, while others fail, as the operation is not atomic.

The subcommand takes no arguments and has no output.

  help

This subcommand shows a summary of all available subcommands with the required arguments.

EXAMPLES

  Download future public keys from an exchange (online)

    $ taler-exchange-offline download > keys.json

  Show information about future public keys (offline or online)

    $ taler-exchange-offline show < keys.json

  Sign future public keys (offline)

    $ taler-exchange-offline sign < keys.json > sigs.json

  Upload signatures about future public keys (online)

    $ taler-exchange-offline upload < sigs.json

  Download, sign and upload, all in one (online)

Note that doing this is only recommended in non-production deployments, as this requires putting the "offline" key onto a system that is actually online!

    $ taler-exchange-offline \
        download \
        sign \
        upload

Here is a variant that shows the output of download, but does not consume it, so that sign can see it as input, as in the variant without show.

    $ taler-exchange-offline \
        download \
        show - \
        sign \
        upload

  Create signature to enable bank account (offline)

The following command sets up an unrestricted simple exchange bank account without conversion:

    $ taler-exchange-offline \
        enable-account payto://iban/DE24242?receiver-name=operator > account.json

The following command would set up an exchange bank account with conversion and restrict it to only receive money from Switzerland and deny its use for debit operations:

    $ taler-exchange-offline \
      enable-account payto://x-taler-bank/example.com/?receiver-name=name \
      conversion-url http://conversion.exchange.com/ \
      debit-restriction \
        deny \
      credit-restriction \
        regex \
          'payto://iban/.*/CH.*?receiver-name=.*' \
          'Swiss only' \
          '{ "de" : "nur Schweiz", \
             "fr" : "Suisse uniquement" }'

  Upload bank account signature (online)

    $ taler-exchange-offline upload < account.json

  Combine signing keys and enabling bank account (offline)

You can chain multiple commands into one invocation:

    $ taler-exchange-offline \
        sign \
        enable-account \
          payto://iban/DE24242 < keys.json > combo.json

Note that sign must be first as it consumes the keys.json input. The resulting output combines the outputs of the sign and enable-account subcommands.

  Upload various signatures (online)

    $ taler-exchange-offline upload < combo.json

  Create multiple revocation messages in one pass (offline)

You can freely combine almost all commands, including those for key revocation:

    $ taler-exchange-offline \
        revoke-denomination $DKH1 \
        revoke-denomination $DKH2 > revoke.json
    $ taler-exchange-offline \
        revoke-signkey $SK1 \
        revoke-signkey $SK2 > revoke.json
    $ taler-exchange-offline \
        revoke-signkey $SK \
        revoke-denomkey $DKH > mix.json

The outputs ("revoke.json", "mix.json") must be uploaded using the upload subcommand to the exchange to actually revoke the keys.

SECURITY CONSIDERATIONS

The taler-exchange-offline tool assumes that it is run on a high-security system with monotonic time. The time does not have to precisely match that of the exchange, but it must be monotonic across tool invocations. The clock of the offline system is used in the enable/disable signatures to communicate an order of the events to the exchange. This prevents someone from replaying an older "enable" (or "disable") message after a more recent "disable" (or "enable") message has been provided to the exchange. Thus, there is no need to keep the actual files exchanged with the offline tool secret.

The taler-exchange-offline tool tries to make sure that the online signing keys of the exchange are always created by the same two security modules. The goal here is to prevent an attacker who compromised taler-exchange-httpd but not the security modules from providing attacker-controlled keys to the offline signing process.

For this, the taler-exchange-offline signing subcommand always automatically learns the security module's public signing key and trusts it on first use (TOFU), but stores it to disk (see the SECM_TOFU_FILE option in the [exchange-offline] section of the configuration). If the keys change subsequently, the tool will refuse to sign.

SEE ALSO

taler-exchange-httpd(1), taler-auditor-offline(1), taler-exchange.conf(5).

BUGS

Report bugs by using https://bugs.taler.net/ or by sending electronic mail to <taler@gnu.org>.

AUTHOR
GNU Taler contributors

COPYRIGHT
2014-2025 Taler Systems SA (GPLv3+ or GFDL 1.3+)