summaryrefslogtreecommitdiff
path: root/taler
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2018-10-10 22:58:50 +0200
committerFlorian Dold <florian.dold@gmail.com>2018-10-10 22:58:50 +0200
commitb1860c12fd3b654efcd0cbb397aa2cd07b16ef69 (patch)
tree24e3a3a17a5dd540bbdd22b7c151a1437ddd110a /taler
parent44e0d2f9fa4e5d4b6354a2cab324ecc87cfc90d3 (diff)
downloaddold-thesis-phd-b1860c12fd3b654efcd0cbb397aa2cd07b16ef69.tar.gz
dold-thesis-phd-b1860c12fd3b654efcd0cbb397aa2cd07b16ef69.tar.bz2
dold-thesis-phd-b1860c12fd3b654efcd0cbb397aa2cd07b16ef69.zip
sync
Diffstat (limited to 'taler')
-rw-r--r--taler/implementation.tex200
1 files changed, 113 insertions, 87 deletions
diff --git a/taler/implementation.tex b/taler/implementation.tex
index 74ab912..35b97f3 100644
--- a/taler/implementation.tex
+++ b/taler/implementation.tex
@@ -351,7 +351,7 @@ Thus the merchant's signature is made over the \emph{contract header},
which contains the contract terms hash, as well as the payment modalities.
In addition to the data provided by the merchant, the contract terms contain a
-\emph{contract\_client\_pub} field whose value is provided by the customer.
+\emph{claim\_pub} field whose value is provided by the customer.
This field is an Ed25519 public key, and the customer can use the corresponding
private key to prove that they have indeed obtained the individual contract
terms from the merchant, and did not copy contract terms that the merchant gave
@@ -451,31 +451,47 @@ donation or shipment tracking information for a physical purchase. A
fulfillment URL does not necessarily refer to a single item, but could also
represent e.g. a shopping basket.
-The following steps illustrate a typical payment with the shop
+The following steps illustrate a typical payment with the online shop
\nolinkurl{alice-shop.example.com}.
-% FIXME: rename fulfillment instance URI to "extended instance URL",
-% use headers instead, say that the extended instance URL is only for legacy compat
+\newcommand{\contl}[0]{\mbox{\textcolor{blue}{$\hookrightarrow$}\space}}
+
+\lstdefinelanguage{none}{
+ identifierstyle=
+}
+\lstdefinestyle{myhttp}{
+ breaklines=true,
+ breakindent=3em,
+ escapechar=*,
+ postbreak=\contl,
+ basicstyle=\ttfamily,
+ showspaces=true,
+}
\begin{enumerate}
\item The user opens the shop's page and navigates to a paid resource, such
as \nolinkurl{https://alice-shop.example.com/essay-24.pdf}.
\item The shop sends a response with HTTP status ``402 Payment Required''
- with the header \texttt{Taler-Contract-Url:
- /contract?product=essay-24.pdf}
+ with the headers (\contl marks a continued line)
+\begin{lstlisting}[style=myhttp]
+Taler-Contract-Url: https://alice-shop.example.com/*\break\contl*contract?product=essay-24.pdf
+Taler-Resource-Url: https://alice-shop.example.com/*\break\contl*essay-24.pdf
+\end{lstlisting}
\item Since the user's wallet does not yet contain contract terms with the
- fulfillment URI \nolinkurl{https://alice-shop.example.com/esasy-24.pdf}, it
- claims the contract by generating a nonce and requesting the URL
- \nolinkurl{https://alice-shop.example.com/contract?product=essay-24.pdf\&nonce=NONCE}.
+ fulfillment URL \nolinkurl{https://alice-shop.example.com/esasy-24.pdf}
+ that matches the resources URL, it claims the contract by generating a
+ claim key pair $(s, p)$ and requesting the contract URL with the claim
+ public key $p$ as additional parameter:
+ \nolinkurl{https://alice-shop.example.com/contract?product=essay-24.pdf\&claim_pub=}$p$.
\item The wallet displays the contract terms to the customer and asks them to
accept or decline. If the customer accepted the contract, the wallet sends
a payment to the merchant. After the merchant received a valid payment,
it marks the corresponding order as paid.
- \item The wallet constructs the fulfillment instance URI by adding the order
+ \item The wallet constructs the extended fulfillment URL by adding the order
id from the contract as an additional parameter and navigates the browser
to the resulting URL
\nolinkurl{https://alice-shop.example.com/esasy-24.pdf?order\_id=...}.
- \item The shop receives the request to the fulfillment instance URI and
+ \item The shop receives the request to the extended fulfillment URI and
checks if the payment corresponding to the order ID was completed. In case
the payment was successful, it serves the purchased content.
\end{enumerate}
@@ -484,10 +500,34 @@ To avoid checking the status of the payment every time, the merchant can
instead set a cookie in the user's browser which indicates that
\texttt{essay-42.pdf} has been purchased.
-If the user returns to the plain fulfillment URI (and does not have a session
-cookie set), the wallet will recognize that the resource has already been paid
-for when receiving the HTTP 402 response from the shop. In this case, the
-wallet navigates to the fulfillment instance URL from an existing purchase.
+The resource-based payment mechanism must also handle the situation where a
+customer navigates again to a resource that they already paid for, without
+directly navigating to the extended fulfillment URL. In case no session cookie
+was set for the purchase or the cookie was deleted/expired, the customer would
+be prompted for a payment again. To avoid this, the wallet tries to find an
+existing contract whose plain fulfillment URL matches the resource URL
+specified in the merchant's HTTP 402 response. If such an existing payment was
+found, the wallet instead redirects the user to the extended fulfillment URL
+for this contract, instead of downloading the new contract terms and prompting
+for payment.
+
+In the example given above, the the URL that triggers the payment is same as the fulfillment URL.
+This may not always the case in practice. When the merchant backend is hosted by a third
+party, say \nolinkurl{https://bob.example.com/}, the page that triggers the payment
+even has a different origin, i.e. the scheme, host or port may differ \cite{rfc6454}.
+
+This cross-origin operation presents a potential privacy risk if not
+implemented carefully.
+To check whether a user has already paid for a particular
+resource with URL $u$, an arbitrary website couly send an HTTP 402 response with
+the ``Taler-Resource-Url'' header set to $u$ and the ``Taler-Contract-Url''
+set to an URL pointing to the attacker's server. If the user paid for $u$, the
+wallet will navigate to the extended fulfillment URL corresponding to $u$.
+Otherwise, the wallet will try to download a contract from the URL given by the
+attacker. In order to prevent this attack on privacy, the wallet must only
+redirect to $u$ if the origin of the page responding with HTTP 402 is the same
+origin as either the $u$ or the pay URI.\footnote{This countermeasure is well
+known in browsers as the same origin policy, as also outlined in \cite{rfc6454}.}
\subsubsection{Loose Browser Integration}
@@ -496,45 +536,20 @@ have native Taler integration, as the browser (or at least a browser extension)
would have to handle the 402 status code and handle the Taler-specific headers correctly.
We now define a fallback, which is transparently implemented in the reference merchant backend.
-Instead of indicating that a payment is required for a resource in the HTTP status code and header,
-the mechant included a fallback URL in the body of the response. This URL must have the custom URL scheme
+In addition to indicating that a payment is required for a resource in the HTTP status code and header,
+the mechant includes a fallback URL in the body of the ``402 Payment Required'' response. This URL must have the custom URL scheme
\texttt{taler}, and contains the contract terms URL (and other Taler-specific settings normally specified in headers)
as parameters. The above payment would include the URL \nolinkurl{taler:pay?contract\_url=\%2Fcontract\%3Fproduct\%3Dessay-24.pdf}.
-\subsubsection{Multiple Origins}
-% FIXME: give illustrative example
-
-The initiation and processing of the payment must be possible from an origin
-that differs from the shop's origin without compromising security of privacy.
-The design discussed so far already allows the pay URL, fulfillment URL and
-contract URL to be on different origins. However, when a payment is triggered
-from a page that differs from the fulfillment URL of the corresponding
-resource, the detection mechanism of the wallet that searches for an existing
-payment for that resource does not work; the user would be asked to repeat the
-payment for something they already purchased.\footnote{
- Note that a 402 response can be given without offering a contract URL to the user,
- for example when a product could be purchased in the past, can still be viewed, but
- not purchased anymore. Thus matching of an existing payment cannot rely on downloading
- the new contract.
-}
-
-To rectify this, the 402 response can specify an additional parameter, the
-``Taler-Resource-Url'' header, which indicates the resource that is the
-subject of the payment request. Unless implemented carefully, this introduces
-a privacy violation: To check whether a user has paid for a particular
-resource with URL $u$, an arbitrary website can send an HTTP 402 response with
-the ``Taler-Resource-Url'' header set to $u$ and the ``Taler-Contract-Url''
-set to an URL pointing to the attacker's server. If the user paid for $u$, the
-wallet will navigate to the fulfillment instance URL corresponding to $u$.
-Otherwise, the wallet will try to download a contract from the URL given by the
-attacker. In order to prevent this attack on privacy, the wallet must only
-redirect to $u$ if the origin of the page responding with HTTP 402 is the same
-origin as either the $u$ or the pay URI.\footnote{This countermeasure is well
-known in browsers as the same origin policy}
+GNU Taler wallet applications registers themselves as a handler for the
+\texttt{taler} URI scheme, and thus following a \texttt{taler:pay} link opens
+the dedicated wallet, even if GNU Taler is not supported by the browser or a
+browser extension. Registration a custom protocol handler for a URI scheme is
+possible on all modern platforms that we are aware of.
-The resource URL can also be set to a random unique identifier to allow
-recurring purchases of the same resource, disabling the wallet's lookup of
-existing payments for the same resource.
+Note that wallets communicating with the merchant do so from a different
+browsing context, and thus the merchant backend cannot rely on cookies that
+were set in the customer's browser when using the shop page.
\subsubsection{Payments for Subresources}
Sometimes subresources (such as embedded videos or images) on a website should
@@ -577,25 +592,27 @@ As a compromise, Taler provides \emph{session-bound} payments. For
session-bound payments, the seller's website assigns the user a random session
ID, for example via a session cookie. The fulfillment instance URL is extended
with an additional parameter \texttt{session\_sig}, which contains proof that
-the user completed the payment under their current session ID or has access to
-the payment receipt in their wallet.
+the user completed (or re-played) the payment under their current session ID.
To initiate a session-bound payment, the HTTP 402 response must additionally
contain the ``Taler-Session-Id'' header, which will cause the wallet to
additionally obtain a signature on the session ID from the merchant's pay URL,
-either by executing (or re-playing)
-the content or by showing the payment receipt together with the session ID.
+by additionally sending the session ID when executing (or re-playing) the
+payment.
+As an optimization, instead of re-playing the full payment, the wallet can also
+send the session ID together with the the payment receipt it obtained from the
+completed payment with different session ID.
Before serving paid content to the user, the merchant simply checks if the
session signature matches the assigned session and contract terms. To simplify
the implementation of the frontend, this signature check can be implemented as
-a request to the Taler backend. Using session signatures instead of storing
+a request to the GU Taler backend. Using session signatures instead of storing
all completed session-bound payments in the merchant's database saves storage.
-While the payment receipt could be shared with other wallets, it is a higher
-barrier than sharing a URL. Furthermore the merchant could restrict the rate
-at which new session can be created for the same contract terms and restrict a
-session to one IP address, limiting sharing.
+While the coins used for the payment or the payment receipt could be shared
+with other wallets, it is a higher barrier than just sharing a URL. Furthermore the
+merchant could restrict the rate at which new sessions can be created for the
+same contract terms and restrict a session to one IP address, limiting sharing.
For the situation where a user accesses a session-bound paid resource and
neither has a corresponding contract in their wallet nor does the merchant
@@ -606,16 +623,20 @@ to the offer URL. As the name suggests, the offer URL can point to a page with
alternative offers for the resource, or some other explanation as to why the
resource is not available anymore.
-\subsection{Privact Implications}
-FIXME: discuss what happens with embedded content
-% Especially of embedded content
+\subsection{Embedded Content}
+
+
\subsection{Refunds}
By signing a \emph{refund permission}, the merchant can ``undo'' a deposit on a
coin, either fully or partially. The customer can then spend (or refresh) the
-refunded of the coin again. A refund is only possible until the refund
-deadline, which is specified in the contract terms and subsequently in the
-deposit permission. Each individual refund on each coin incurs fees; the
+refunded value of the coin again. A refund is only possible until the refund
+deadline (specified in the contract header). After the refund deadline has
+passed (and before the deposit deadline) the exchange makes a bank transfer the
+merchant with the aggregated value from deposits, a refund after this point
+would require a bank transfer back from the merchant to the exchange.
+
+Each individual refund on each coin incurs fees; the
refund fee is subtracted from the amount given back to the customer and kept be
the exchange.
@@ -640,20 +661,21 @@ merchant received from the exchange.
\subsection{Tipping}
Tipping in Taler uses the ``withdraw loophole'' (see \ref{XXX}) to allow the
-merchant to pay small amounts (without any associated contract terms or legal
-obligations!) into the customer's wallet.
+merchant\footnote{We still use the term ``merchant'', since donations use the same software component
+as the merchant, but ``donor'' would be more accurate.} to donate small amounts (without any associated contract terms or legal
+obligations) into the user's wallet.
To be able to give tips, the merchant must create a reserve with an exchange. The reserve private key
-is used to sign blinded coins (planchets) generated by the user that is being given the tip.
+is used to sign blinded coins generated by the user that is being given the tip.
-The merchant triggers giving a tip with a HTTP 402 response that has the ``X-Taler-Tip'' header. The value
+The merchant triggers giving a tip with a HTTP 402 response that has the ``Taler-Tip'' header. The value
of the tip header (called the tip token) contains
\begin{itemize}
\item the amount of the tip,
\item the exchange to use,
- \item a URL to redirect after processing the tip
- \item a deadline for picking up the tip
- \item a merchant-internal unique ID for the tip
+ \item a URL to redirect after processing the tip,
+ \item a deadline for picking up the tip,
+ \item a merchant-internal unique ID for the tip, and
\item the \emph{pickup URL} for the tip.
\end{itemize}
Upon receiving the tip token, the wallet creates coin planchets that sum up to at most
@@ -674,15 +696,17 @@ contain the following information:
\begin{itemize}
\item The total amount to be paid,
\item the \texttt{pay\_url}, an HTTP endpoint that receives the payment,
- \item the deadline until the merchant accepts the payment,
- \item the nonce used by the customer to prove they have claimed the contract terms,
+ \item the deadline until the merchant accepts the payment (repeated in the signed contract header),
+ \item the deadline for refunds (repeated in the signed contract header),
+ \item the nonce claim public key provided by the customer, used to prove they have claimed the contract terms,
\item the order ID, which is a short, human-friendly identifier for the contract terms within
- the merchant, (FIXME: order ID should be explained earlier)
+ the merchant,
\item the \texttt{fulfillment\_url}, which identifies the resources that is being paid for
\item a human-readable summary and product list,
- \item the fees covered by the merchant, (FIXME: more detail)
- \item the deadline for refunds,
- \item the hashed bank account information of the merchant (needed by the wallet to sign the deposit permissions),
+ \item the fees covered by the merchant (if the fees for the payment exceed this value, the
+ customer must explicitly pay the additional fees),
+ \item depending on the underlying payment system, KYC registration information
+ or other payment-related data that needs to be passed on to the exchange (repeated in the signed contract header),
\item the list of exchanges and auditors that the merchants accepts for the payment,
\item information about the merchant, including the merchant public key and contact information.
\end{itemize}
@@ -730,7 +754,7 @@ destroyed by the navigation. Instead the wallet can offer a JavaScript-based
API, exposed as a single function with a subset of the parameters of the
402-based payment: \texttt{contract\_url}, \texttt{resource\_url},
\texttt{session\_id} \texttt{refund\_url}, \texttt{offer\_url},
-\texttt{tip\_token}). Instead of navigating away, the result of the operation
+\texttt{tip\_token}. Instead of navigating away, the result of the operation
is returned as a JavaScript promise (either a payment receipt, refund
confirmation, tip success status or error). If user input is required (e.g. to
ask for a confirmation for a payment), the page's status must not be destroyed.
@@ -785,18 +809,20 @@ In the implementation of Taler, \texttt{payto} URIs are used in various places:
that already contains the reserve public key. When scanning the QR code with a mobile device that
has an appropriate banking app installed, a bank transfer form can be pre-filled and the user only has to confirm the
transfer to the exchange.
- \item The merchant specifies the account he wishes to be paid on as a \texttt{payto} URI
+ \item The merchant specifies the account he wishes to be paid on as a \texttt{payto} URI, both in
+ the configuration of the merchant backend as well as in communication with the exchange.
\end{enumerate}
A major advantage of encoding payment targets as URIs is that URI schemes can be registered
with an application on most platforms, and will be ``clickable'' in most applications and open the right
-application when scanned as a QR code.
+application when scanned as a QR code. This is especially useful for the first use case listed above; the other use cases
+could be covered by defining a media type instead \cite{rfc6838}.
\subsection{Demo Bank}
For demonstration purposes and integration testing we use our toy bank
implementation, which might be used in the future for regional currencies or
accounting systems (e.g. for a company cafeteria). The payment type identifier
-is \texttt{x-taler-bank}. The authority part encodes the base URL of the bank,
+is \texttt{taler-bank}. The authority part encodes the base URL of the bank,
and the path must be a single component with in integer between $1$ and $2^52$.
\section{Exchange}
@@ -881,7 +907,7 @@ The \texttt{taler-auditor} process generates a report with the following informa
keys recorded in deposit/refresh operations smaller or equal to the number
of blind signatures recorded in withdraw/refresh operations?
If this invariant is violated, the corresponding denomination must be revoked.
- \item Are signatures made by the exchange correct?
+ %\item Are signatures made by the exchange correct? (no, apparently we don't store signatures)
\item What is the income if the exchange from different fees?
\end{itemize}
@@ -891,7 +917,7 @@ for the incremental computation. Most database tables used by the exchange are
append-only: rows are only added but never removed or changed. Tables that
are destructively modified by the exchange only store cached computations based
on the append-only tables. Each append-only table has a monotonically
-increasind row ID. Thus the auditor's checkpoint simply consists of the set of
+increasing row ID. Thus the auditor's checkpoint simply consists of the set of
row IDs that were last seen.
In future versions, the auditor will also have a \emph{taler-auditor-httpd}
@@ -911,16 +937,16 @@ handles cryptographic operations (signature verification, signing), secret
management and communication with the exchange.
The backend API is divided into two types of HTTP endpoints: \begin{enumerate}
- \item Functionality that is accessed by the merchant. These APIs typically
+ \item Functionality that is accessed internally by the merchant. These APIs typically
require authentication and/or are only accessible from within the private
network of the merchant.
- \item Functionality that is accessed by the customer's wallet and browser.
+ \item Functionality that is exposed publicly on the Internet and accessed by the customer's wallet and browser.
% FIXME: talk about proxying
\end{enumerate}
A typical merchant has a \emph{storefront} component that customers visit with
their browser, as well as a \emph{back office} component that allows the
-merchant to view information about payments that customers made and integrates
+merchant to view information about payments that customers made and that integrates
with other components such as order processing and shipping.
\subsection{Processing payments}