lsd0009

LSD0009: The GNU Taler Protocol
Log | Files | Refs | README

draft-guetschow-taler-protocol.xml (82081B)


      1 <?xml version='1.0' encoding='utf-8'?>
      2 <!DOCTYPE rfc [
      3   <!ENTITY nbsp    "&#160;">
      4   <!ENTITY zwsp   "&#8203;">
      5   <!ENTITY nbhy   "&#8209;">
      6   <!ENTITY wj     "&#8288;">
      7 ]>
      8 <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
      9 <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.35 (Ruby 3.1.2) -->
     10 <rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-guetschow-taler-protocol" category="info" submissionType="independent" tocInclude="true" sortRefs="true" symRefs="true" version="3">
     11   <!-- xml2rfc v2v3 conversion 3.32.0 -->
     12   <front>
     13     <title>The GNU Taler Protocol</title>
     14     <seriesInfo name="Internet-Draft" value="draft-guetschow-taler-protocol"/>
     15     <author initials="M." surname="Gütschow" fullname="Mikolai Gütschow">
     16       <organization abbrev="TU Dresden">TUD Dresden University of Technology</organization>
     17       <address>
     18         <postal>
     19           <street>Helmholtzstr. 10</street>
     20           <city>Dresden</city>
     21           <code>D-01069</code>
     22           <country>Germany</country>
     23         </postal>
     24         <email>mikolai.guetschow@tu-dresden.de</email>
     25       </address>
     26     </author>
     27     <date year="2026" month="April" day="30"/>
     28     <workgroup>independent</workgroup>
     29     <keyword>taler</keyword>
     30     <keyword>cryptography</keyword>
     31     <keyword>ecash</keyword>
     32     <keyword>payments</keyword>
     33     <abstract>
     34       <?line 45?>
     35 
     36 <t>[ TBW ]</t>
     37     </abstract>
     38   </front>
     39   <middle>
     40     <?line 49?>
     41 
     42 <section anchor="introduction">
     43       <name>Introduction</name>
     44       <t>[ TBW ]</t>
     45       <t>Beware that this document is still work-in-progress and may contain errors.
     46 Use at your own risk!</t>
     47     </section>
     48     <section anchor="notation">
     49       <name>Notation</name>
     50       <ul spacing="normal">
     51         <li>
     52           <t><tt>"abc"</tt> denotes the literal string <tt>abc</tt> encoded as ASCII <xref target="RFC20"/></t>
     53         </li>
     54         <li>
     55           <t><tt>a | b</tt> denotes the concatenation of a with b</t>
     56         </li>
     57         <li>
     58           <t><tt>len(a)</tt> denotes the length in bytes of the byte string a</t>
     59         </li>
     60         <li>
     61           <t><tt>padZero(y, a)</tt> denotes the byte string a, zero-padded to the length of y bytes</t>
     62         </li>
     63         <li>
     64           <t><tt>bits(x)</tt>/<tt>bytes(x)</tt> denotes the minimal number of bits/bytes necessary to represent the multiple precision integer x</t>
     65         </li>
     66         <li>
     67           <t><tt>uint(y, x)</tt> denotes the <tt>y</tt> least significant bits of the integer <tt>x</tt>, zero-padded and encoded in network byte order (big endian)</t>
     68         </li>
     69         <li>
     70           <t><tt>uintY(x)</tt> where <tt>Y</tt> is a positive integer number is equivalent to <tt>uint(Y, x)</tt></t>
     71         </li>
     72         <li>
     73           <t><tt>random(y)</tt> denotes a randomly generated sequence of y bits</t>
     74         </li>
     75         <li>
     76           <t><tt>a * b (mod N)</tt> / <tt>a ** b (mod N)</tt> denotes the multiplication / exponentiation of multiple precision integers a and b, modulo N</t>
     77         </li>
     78         <li>
     79           <t><tt>for</tt>, <tt>if</tt>, variable assignment <tt>=</tt>, and conditional operators are to be interpreted like their Python/Julia equivalents</t>
     80         </li>
     81         <li>
     82           <t><tt>data.key</tt> denotes the property <tt>key</tt> on the object <tt>data</tt></t>
     83         </li>
     84         <li>
     85           <t><tt>0..n</tt> denotes the exclusive range of integer numbers from <tt>0</tt> to <tt>n</tt>, i.e., <tt>0, 1, 2, ..., n-1</tt></t>
     86         </li>
     87         <li>
     88           <t><tt>⟨dataᵢ⟩</tt> within a context of <tt>i = 0..n</tt> denotes <tt>n</tt> objects <tt>dataᵢ</tt>, represented in memory as a continuous array</t>
     89         </li>
     90         <li>
     91           <t><tt>⟨dataᵢ.key⟩</tt> within a context of <tt>i = 0..n</tt> denotes an array of the <tt>n</tt> properties <tt>key</tt> of all <tt>n</tt> objects <tt>dataᵢ</tt></t>
     92         </li>
     93       </ul>
     94     </section>
     95     <section anchor="cryptographic-primitives">
     96       <name>Cryptographic Primitives</name>
     97       <t>// todo: maybe change this description to something more similar to protocol functions (Julia-inspired syntax)</t>
     98       <section anchor="cryptographic-hash-functions">
     99         <name>Cryptographic Hash Functions</name>
    100         <section anchor="sha256">
    101           <name>SHA-256</name>
    102           <artwork><![CDATA[
    103 SHA-256(msg) -> hash
    104 
    105 Input:
    106     msg     input message of length L < 2^61 octets
    107 
    108 Output:
    109     hash    message digest of fixed length HashLen = 32 octets
    110 ]]></artwork>
    111           <t><tt>hash</tt> is the output of SHA-256 as per Sections 4.1, 5.1, 6.1, and 6.2 of <xref target="RFC6234"/>.</t>
    112         </section>
    113         <section anchor="sha512">
    114           <name>SHA-512</name>
    115           <artwork><![CDATA[
    116 SHA-512(msg) -> hash
    117 
    118 Input:
    119     msg     input message of length L < 2^125 octets
    120 
    121 Output:
    122     hash    message digest of fixed length HashLen = 64 octets
    123 ]]></artwork>
    124           <t><tt>hash</tt> is the output of SHA-512 as per Sections 4.2, 5.2, 6.3, and 6.4 of <xref target="RFC6234"/>.</t>
    125         </section>
    126         <section anchor="sha512-trunc">
    127           <name>SHA-512-256 (truncated SHA-512)</name>
    128           <artwork><![CDATA[
    129 SHA-512-256(msg) -> hash
    130 
    131 Input:
    132     msg     input message of length L < 2^125 octets
    133 
    134 Output:
    135     hash    message digest of fixed length HashLen = 32 octets
    136 ]]></artwork>
    137           <t>The output <tt>hash</tt> corresponds to the first 32 octets of the output of SHA-512 defined in <xref target="sha512"/>:</t>
    138           <artwork><![CDATA[
    139 temp = SHA-512(msg)
    140 hash = temp[0:31]
    141 ]]></artwork>
    142           <t>Note that this operation differs from SHA-512/256 as defined in <xref target="SHS"/> in the initial hash value.</t>
    143         </section>
    144       </section>
    145       <section anchor="message-authentication-codes">
    146         <name>Message Authentication Codes</name>
    147         <section anchor="hmac">
    148           <name>HMAC</name>
    149           <artwork><![CDATA[
    150 HMAC-Hash(key, text) -> out
    151 
    152 Option:
    153     Hash    cryptographic hash function with output length HashLen
    154 
    155 Input:
    156     key     secret key of length at least HashLen
    157     text    input data of arbitary length
    158 
    159 Output:
    160     out     output of length HashLen
    161 ]]></artwork>
    162           <t><tt>out</tt> is calculated as defined in <xref target="RFC2104"/>.</t>
    163         </section>
    164       </section>
    165       <section anchor="key-derivation-functions">
    166         <name>Key Derivation Functions</name>
    167         <section anchor="hkdf">
    168           <name>HKDF</name>
    169           <t>The Hashed Key Derivation Function (HKDF) used in Taler is an instantiation of <xref target="RFC5869"/>
    170 with two different hash functions for the Extract and Expand step as suggested in <xref target="HKDF"/>:
    171 <tt>HKDF-Extract</tt> uses <tt>HMAC-SHA512</tt>, while <tt>HKDF-Expand</tt> uses <tt>HMAC-SHA256</tt> (cf. <xref target="hmac"/>).</t>
    172           <artwork><![CDATA[
    173 HKDF(salt, IKM, info, L) -> OKM
    174 
    175 Inputs:
    176     salt    optional salt value (a non-secret random value);
    177               if not provided, it is set to a string of 64 zeros.
    178     IKM     input keying material
    179     info    optional context and application specific information
    180               (can be a zero-length string)
    181     L       length of output keying material in octets
    182               (<= 255*32 = 8160)
    183 
    184 Output:
    185     OKM      output keying material (of L octets)
    186 ]]></artwork>
    187           <t>The output OKM is calculated as follows:</t>
    188           <artwork><![CDATA[
    189 PRK = HKDF-Extract(salt, IKM) with Hash = SHA-512 (HashLen = 64)
    190 OKM = HKDF-Expand(PRK, info, L) with Hash = SHA-256 (HashLen = 32)
    191 ]]></artwork>
    192         </section>
    193         <section anchor="hkdf-mod">
    194           <name>HKDF-Mod</name>
    195           <t>Based on the HKDF defined in <xref target="hkdf"/>, this function returns an OKM that is smaller than a given multiple precision integer N.</t>
    196           <artwork><![CDATA[
    197 HKDF-Mod(N, salt, IKM, info) -> OKM
    198 
    199 Inputs:
    200     N        multiple precision integer
    201     salt     optional salt value (a non-secret random value);
    202               if not provided, it is set to a string of 64 zeros.
    203     IKM      input keying material
    204     info     optional context and application specific information
    205               (can be a zero-length string)
    206 
    207 Output:
    208     OKM      output keying material (smaller than N)
    209 ]]></artwork>
    210           <t>The final output <tt>OKM</tt> is determined deterministically based on a counter initialized at zero.</t>
    211           <artwork><![CDATA[
    212 counter = 0
    213 do until OKM < N:
    214     x = HKDF(salt, IKM, info | uint16(counter), bytes(N))
    215     OKM = uint(bits(N), x)
    216     counter += 1
    217 ]]></artwork>
    218         </section>
    219       </section>
    220       <section anchor="non-blind-signatures">
    221         <name>Non-Blind Signatures</name>
    222         <section anchor="ed25519">
    223           <name>Ed25519</name>
    224           <t>Taler uses EdDSA instantiated with curve25519 as Ed25519,
    225 as defined in Section 5.1 of <xref target="RFC8032"/>.
    226 In particular, Taler does <em>not</em> make use of Ed25519ph or Ed25519ctx
    227 as defined in that document.</t>
    228           <section anchor="key-generation">
    229             <name>Key generation</name>
    230             <artwork><![CDATA[
    231 Ed25519-GetPub(priv) -> pub
    232 
    233 Input:
    234     priv    private Ed25519 key
    235 
    236 Output:
    237     pub     public Ed25519 key
    238 ]]></artwork>
    239             <t><tt>pub</tt> is calculated as described in Section 5.1.5 of <xref target="RFC8032"/>.</t>
    240             <artwork><![CDATA[
    241 Ed25519-Keygen() -> (priv, pub)
    242 
    243 Output:
    244     priv    private Ed25519 key
    245     pub     public Ed25519 key
    246 ]]></artwork>
    247             <t><tt>priv</tt> and <tt>pub</tt> are calculated as described in Section 5.1.5 of <xref target="RFC8032"/>,
    248 which is equivalent to the following:</t>
    249             <artwork><![CDATA[
    250 priv = random(256)
    251 pub = Ed25519-GetPub(priv)
    252 ]]></artwork>
    253           </section>
    254           <section anchor="signing">
    255             <name>Signing</name>
    256             <artwork><![CDATA[
    257 Ed25519-Sign(priv, msg) -> sig
    258 
    259 Inputs:
    260     priv    Ed25519 private key
    261     msg     message to be signed
    262 
    263 Output:
    264     sig     signature on the message by the given private key
    265 ]]></artwork>
    266             <t><tt>sig</tt> is calculated as described in Section 5.1.6 of <xref target="RFC8032"/>.</t>
    267           </section>
    268           <section anchor="verifying">
    269             <name>Verifying</name>
    270             <artwork><![CDATA[
    271 Ed25519-Verify(pub, msg, sig) -> out
    272 
    273 Inputs:
    274     pub     Ed25519 public key
    275     msg     signed message
    276     sig     signature on msg
    277 
    278 Output:
    279     out     true, if sig is a valid signature for msg
    280 ]]></artwork>
    281             <t><tt>out</tt> is the outcome of the last check of Section 5.1.7 of <xref target="RFC8032"/>.</t>
    282           </section>
    283         </section>
    284       </section>
    285       <section anchor="key-agreement">
    286         <name>Key Agreement</name>
    287         <section anchor="x25519">
    288           <name>X25519</name>
    289           <t>Taler uses Elliptic Curve Diffie-Hellman (ECDH) on curve25519 as defined in Section 6.1 of <xref target="RFC7748"/>,
    290 but reuses Ed25519 keypairs for one side of the agreement instead of random bytes.
    291 Depending on whether the private or public part is from Ed25519, two different functions are used.</t>
    292           <artwork><![CDATA[
    293 ECDH-Ed25519-Priv(priv, pub) -> shared
    294 
    295 Input:
    296     priv    private Ed25519 key
    297     pub     public X25519 key
    298 
    299 Output:
    300     shared  shared secret based on the given keys
    301 ]]></artwork>
    302           <t><tt>shared</tt> is calculated as follows, using the function X25519 defined in Section 5 of <xref target="RFC7748"/>:</t>
    303           <artwork><![CDATA[
    304 priv' = SHA-512-256(priv)
    305 // todo: missing bit clamping from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_sign/ed25519/ref10/keypair.c#L71
    306 shared' = X25519(priv', pub)
    307 shared = SHA-512(shared')
    308 ]]></artwork>
    309           <artwork><![CDATA[
    310 ECDH-Ed25519-Pub(priv, pub) -> shared
    311 
    312 Input:
    313     priv    private X25519 key
    314     pub     public Ed25519 key
    315 
    316 Output:
    317     shared  shared secret based on the given keys
    318 ]]></artwork>
    319           <t><tt>shared</tt> is calculated as follows, using the function X25519 defined in Section 5 of <xref target="RFC7748"/>,
    320 and <tt>Convert-Point-Ed25519-Curve25519(p)</tt> which implements the birational map of Section 4.1 of <xref target="RFC7748"/>:</t>
    321           <artwork><![CDATA[
    322 pub' = Convert-Point-Ed25519-Curve25519(pub)
    323 shared' = X25519(priv, pub')
    324 shared = SHA-512(shared')
    325 ]]></artwork>
    326           <artwork><![CDATA[
    327 ECDH-GetPub(priv) -> pub
    328 
    329 Input:
    330     priv    private X25519 key
    331 
    332 Output:
    333     pub     public X25519 key
    334 ]]></artwork>
    335           <t><tt>pub</tt> is calculated according to Section 6.1 of <xref target="RFC7748"/>:</t>
    336           <artwork><![CDATA[
    337 pub = X25519(priv, 9)
    338 ]]></artwork>
    339         </section>
    340       </section>
    341       <section anchor="blind-signatures">
    342         <name>Blind Signatures</name>
    343         <section anchor="rsa-fdh">
    344           <name>RSA-FDH</name>
    345           <section anchor="supporting-functions">
    346             <name>Supporting Functions</name>
    347             <artwork><![CDATA[
    348 RSA-FDH(msg, pubkey) -> fdh
    349 
    350 Inputs:
    351     msg     message
    352     pubkey  RSA public key consisting of modulus N and public exponent e
    353 
    354 Output:
    355     fdh     full-domain hash of msg over pubkey.N
    356 ]]></artwork>
    357             <t><tt>fdh</tt> is calculated based on HKDF-Mod from <xref target="hkdf-mod"/> as follows:</t>
    358             <artwork><![CDATA[
    359 info = "RSA-FDA FTpsW!"
    360 salt = uint16(bytes(pubkey.N)) | uint16(bytes(pubkey.e))
    361      | pubkey.N | pubkey.e
    362 fdh = HKDF-Mod(pubkey.N, salt, msg, info)
    363 ]]></artwork>
    364             <t>The resulting <tt>fdh</tt> can be used to test against a malicious RSA pubkey
    365 by verifying that the greatest common denominator (gcd) of <tt>fdh</tt> and <tt>pubkey.N</tt> is 1.</t>
    366             <artwork><![CDATA[
    367 RSA-FDH-Derive(bks, pubkey) -> out
    368 
    369 Inputs:
    370     bks     blinding key secret of length L = 32 octets
    371     pubkey  RSA public key consisting of modulus N and public exponent e
    372 
    373 Output:
    374     out     full-domain hash of bks over pubkey.N
    375 ]]></artwork>
    376             <t><tt>out</tt> is calculated based on HKDF-Mod from <xref target="hkdf-mod"/> as follows:</t>
    377             <artwork><![CDATA[
    378 info = "Blinding KDF"
    379 salt = "Blinding KDF extractor HMAC key"
    380 fdh = HKDF-Mod(pubkey.N, salt, bks, info)
    381 ]]></artwork>
    382           </section>
    383           <section anchor="blinding">
    384             <name>Blinding</name>
    385             <artwork><![CDATA[
    386 RSA-FDH-Blind(msg, bks, pubkey) -> out
    387 
    388 Inputs:
    389     msg     message
    390     bks     blinding key secret of length L = 32 octets
    391     pubkey  RSA public key consisting of modulus N and public exponent e
    392 
    393 Output:
    394     out     message blinded for pubkey
    395 ]]></artwork>
    396             <t><tt>out</tt> is calculated based on RSA-FDH from <xref target="rsa-fdh"/> as follows:</t>
    397             <artwork><![CDATA[
    398 data = RSA-FDH(msg, pubkey)
    399 r = RSA-FDH-Derive(bks, pubkey)
    400 r_e = r ** pubkey.e (mod pubkey.N)
    401 out = r_e * data (mod pubkey.N)
    402 ]]></artwork>
    403           </section>
    404           <section anchor="signing-1">
    405             <name>Signing</name>
    406             <artwork><![CDATA[
    407 RSA-FDH-Sign(data, privkey) -> sig
    408 
    409 Inputs:
    410     data    data to be signed, an integer smaller than privkey.N
    411     privkey RSA private key consisting of modulus N and private exponent d
    412 
    413 Output:
    414     sig     signature on data by privkey
    415 ]]></artwork>
    416             <t><tt>sig</tt> is calculated as follows:</t>
    417             <artwork><![CDATA[
    418 sig = data ** privkey.d (mod privkey.N)
    419 ]]></artwork>
    420           </section>
    421           <section anchor="unblinding">
    422             <name>Unblinding</name>
    423             <artwork><![CDATA[
    424 RSA-FDH-Unblind(sig, bks, pubkey) -> out
    425 
    426 Inputs:
    427     sig     blind signature
    428     bks     blinding key secret of length L = 32 octets
    429     pubkey  RSA public key consisting of modulus N and public exponent e
    430 
    431 Output:
    432     out     unblinded signature
    433 ]]></artwork>
    434             <t><tt>out</tt> is calculated as follows:</t>
    435             <artwork><![CDATA[
    436 r = RSA-FDH-Derive(bks, pubkey)
    437 r_inv = inverse of r (mod pubkey.N)
    438 out = sig * r_inv (mod pubkey.N)
    439 ]]></artwork>
    440           </section>
    441           <section anchor="verifying-1">
    442             <name>Verifying</name>
    443             <artwork><![CDATA[
    444 RSA-FDH-Verify(msg, sig, pubkey) -> out
    445 
    446 Inputs:
    447     msg     message
    448     sig     signature of pubkey over msg
    449     pubkey  RSA public key consisting of modulus N and public exponent e
    450 
    451 Output:
    452     out     true, if sig is a valid signature
    453 ]]></artwork>
    454             <t><tt>out</tt> is calculated based on RSA-FDH from <xref target="rsa-fdh"/> as follows:</t>
    455             <artwork><![CDATA[
    456 data = RSA-FDH(msg, pubkey)
    457 exp = sig ** pubkey.e (mod pubkey.N)
    458 out = (data == exp)
    459 ]]></artwork>
    460           </section>
    461         </section>
    462         <section anchor="clause-schnorr">
    463           <name>Clause-Schnorr</name>
    464         </section>
    465       </section>
    466     </section>
    467     <section anchor="datatypes-and-notation">
    468       <name>Datatypes and Notation</name>
    469       <section anchor="amounts">
    470         <name>Amounts</name>
    471         <t>Amounts are represented in Taler as positive fixed-point values
    472 consisting of <tt>value</tt> as the non-negative integer part of the base currency,
    473 the <tt>fraction</tt> given in units of one hundred millionth (1e-8) of the base currency,
    474 and <tt>currency</tt> as the 3-11 ASCII characters identifying the currency.</t>
    475         <t>Whenever used in the protocol, the binary representation of an <tt>amount</tt> is
    476 <tt>uint64(amount.value) | uint32(amount.fraction) | padZero(12, amount.currency)</tt>.</t>
    477       </section>
    478       <section anchor="timestamps">
    479         <name>Timestamps</name>
    480         <t>Absolute timestamps are represented as <tt>uint64(x)</tt> where <tt>x</tt> corresponds to
    481 the microseconds since <tt>1970-01-01 00:00 CEST</tt> (the UNIX epoch).
    482 The special value <tt>0xFFFFFFFFFFFFFFFF</tt> represents "never".
    483 <!--
    484 // todo: check if needed and correct
    485 Relative timestamps are represented as `uint64(x)` where `x` is given in microseconds.
    486 The special value `0xFFFFFFFFFFFFFFFF` represents "forever".
    487 -->
    488         </t>
    489       </section>
    490       <section anchor="signatures">
    491         <name>Signatures</name>
    492         <t>All messages to be signed in Taler start with a header containing their size and
    493 a fixed signing context (purpose) as registered by GANA in the
    494 <eref target="https://gana.gnunet.org/gnunet-signatures/gnunet_signatures.html">GNUnet Signature Purposes</eref>
    495 registry. Taler-related purposes start at 1000.</t>
    496         <artwork><![CDATA[
    497 Gen-Msg(purpose, msg) -> out
    498 
    499 Inputs:
    500     purpose signature purpose as registered at GANA
    501     msg     message content (excl. header) to be signed
    502 
    503 Output:
    504     out     complete message (incl. header) to be signed
    505 ]]></artwork>
    506         <t><tt>out</tt> is formed as follows:</t>
    507         <artwork><![CDATA[
    508 out = uint32(len(msg)) | uint32(purpose) | msg
    509 ]]></artwork>
    510       </section>
    511       <section anchor="helper-functions">
    512         <name>Helper Functions</name>
    513         <t>There are a certain number of single-argument functions which are often needed,
    514 and therefore omit the parentheses of the typical function syntax:</t>
    515         <ul spacing="normal">
    516           <li>
    517             <t><tt>Knows data</tt> specifies <tt>data</tt> that is known a priori at the start of the protocol operation</t>
    518           </li>
    519           <li>
    520             <t><tt>Check cond</tt> verifies that the boolean condition or variable <tt>cond</tt> is true,
    521 or aborts the protocol operation otherwise</t>
    522           </li>
    523           <li>
    524             <t><tt>Persist data</tt> persists the given <tt>data</tt> to the local database</t>
    525           </li>
    526           <li>
    527             <t><tt>data = Lookup by key</tt> retrieves previously persisted <tt>data</tt> by the given <tt>key</tt></t>
    528           </li>
    529           <li>
    530             <t><tt>Sum ⟨dataᵢ⟩</tt> is valid for numerical objects <tt>dataᵢ</tt> including amounts (cf. <xref target="amounts"/>),
    531 and denotes the numerical sum of these objects</t>
    532           </li>
    533         </ul>
    534         <t>Some more functions that are commonly used throughout <xref target="protocol"/>:</t>
    535         <artwork><![CDATA[
    536 Hash-Denom(denom) =
    537   SHA-512(uint32(0) | uint32(1) | denom.pub)
    538 
    539 Hash-Planchet(planchet, denom) =
    540   SHA-512( SHA-512( denom.pub ) | uint32(0x1) | planchet )
    541 
    542 Check-Subtract(value, subtrahend) =
    543   Check value >= subtrahend
    544   Persist value -= subtrahend
    545 ]]></artwork>
    546       </section>
    547     </section>
    548     <section anchor="protocol">
    549       <name>The Taler Crypto Protocol</name>
    550       <t>// todo: briefly introduce the three components wallet, exchange, merchant; maybe with ASCII diagram version</t>
    551       <t>// todo: capitalize wallet, exchange, merchant?</t>
    552       <section anchor="obtaining-e-cash">
    553         <name>Obtaining E-Cash</name>
    554         <section anchor="withdraw">
    555           <name>Withdrawal</name>
    556           <t>The wallet generates <tt>n &gt; 0</tt> coins <tt>⟨coinᵢ⟩</tt> and requests <tt>n</tt> signatures <tt>⟨blind_sigᵢ⟩</tt> from the exchange,
    557 attributing value to the coins according to <tt>n</tt> chosen denominations <tt>⟨denomᵢ⟩</tt>.
    558 The total value and withdrawal fee (defined by the exchange per denomination)
    559 must be smaller or equal to the amount stored in the single reserve used for withdrawal.</t>
    560           <t>// todo: document TALER_MAX_COINS = 64 per operation (due to CS-encoding)</t>
    561           <t>// todo: extend with extra roundtrip for CBS</t>
    562           <artwork><![CDATA[
    563             wallet                                  exchange
    564 Knows ⟨denomᵢ⟩                          Knows ⟨denomᵢ.priv⟩
    565                |                                        |
    566 +-----------------------------+                         |
    567 | (W1) reserve key generation |                         |
    568 +-----------------------------+                         |
    569                |                                        |
    570                |----------- (bank transfer) ----------->|
    571                | (subject: reserve.pub, amount: value)  |
    572                |                                        |
    573                |                      +------------------------------+
    574                |                      | Persist (reserve.pub, value) |
    575                |                      +------------------------------+
    576                |                                        |
    577 +-----------------------------------+                   |
    578 | (W2) coin generation and blinding |                   |
    579 +-----------------------------------+                   |
    580                |                                        |
    581                |-------------- /withdraw -------------->|
    582                |    (reserve.pub, planchets, sig)       |
    583                |                                        |
    584                |                      +--------------------------------+
    585                |                      | (E1) coin issuance and signing |
    586                |                      +--------------------------------+
    587                |                                        |
    588                |<---------- (⟨blind_sigᵢ⟩) -------------|
    589                |                                        |
    590 +----------------------+                                |
    591 | (W3) coin unblinding |                                |
    592 +----------------------+                                |
    593                |                                        |
    594 ]]></artwork>
    595           <t>where (for RSA, without age-restriction)</t>
    596           <artwork><![CDATA[
    597 (W1) reserve key generation (wallet)
    598 
    599 reserve = Ed25519-Keygen()
    600 Persist (reserve, value)
    601 ]]></artwork>
    602           <t>The wallet derives coins and blinding secrets using a HKDF from a single seed per withdrawal operation,
    603 together with an integer index.
    604 This is strictly speaking an implementation detail since the seed is never revealed to any other party,
    605 and might be chosen to be implemented differently.</t>
    606           <t>// todo: blind_secret/coin.priv differently generated in TALER_EXCHANGE_post_withdraw_start/prepare_coins, double check with wallet-core (probably implementation detail here)</t>
    607           <artwork><![CDATA[
    608 (W2) coin generation and blinding (wallet)
    609 
    610 batch_seed = random(256)
    611 Persist batch_seed
    612 for i in 0..n:
    613   coin_seedᵢ = HKDF(uint32(i), batch_seed, "taler-withdrawal-coin-derivation", 64)
    614   blind_secretᵢ = coin_seedᵢ[32:]
    615   coinᵢ.priv = coin_seedᵢ[:32]
    616   coinᵢ.pub = Ed25519-GetPub(coinᵢ.priv)
    617   h_denomᵢ = Hash-Denom(denomᵢ)
    618   planchetᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
    619   h_planchetᵢ = Hash-Planchet(planchetᵢ, denomᵢ)
    620 planchets = (⟨h_denomᵢ⟩, ⟨planchetᵢ⟩)
    621 msg = Gen-Msg(WALLET_RESERVE_WITHDRAW,
    622     ( Sum ⟨denomᵢ.value⟩ | Sum ⟨denomᵢ.fee_withdraw⟩
    623     | SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
    624 sig = Ed25519-Sign(reserve.priv, msg)
    625 ]]></artwork>
    626           <artwork><![CDATA[
    627 (E1) coin issuance and signing (exchange)
    628 
    629 (⟨h_denomᵢ⟩, ⟨planchetᵢ⟩) = planchets
    630 for i in 0..n:
    631   denomᵢ = Lookup by h_denomᵢ
    632   Check denomᵢ known and not withdraw-expired
    633   h_planchetᵢ = Hash-Planchet(planchetᵢ, denomᵢ)
    634 msg = Gen-Msg(WALLET_RESERVE_WITHDRAW,
    635     ( Sum ⟨denomᵢ.value⟩ | Sum ⟨denomᵢ.fee_withdraw⟩
    636     | SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
    637 Check Ed25519-Verify(reserve.pub, msg, sig)
    638 Check reserve KYC status ok or not needed
    639 total = Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
    640 Check-Subtract(reserve.balance, total)
    641 for i in 0..n:
    642   blind_sigᵢ = RSA-FDH-Sign(planchetᵢ, denomᵢ.priv)
    643 Persist withdrawal // todo: what exactly? should be checked first for replay?
    644 ]]></artwork>
    645           <artwork><![CDATA[
    646 (W3) coin unblinding (wallet)
    647 
    648 for i in 0..n:
    649   coinᵢ.sig = RSA-FDH-Unblind(blind_sigᵢ, blind_secretᵢ, denomᵢ.pub)
    650   Check RSA-FDH-Verify(SHA-512(coinᵢ.pub), coinᵢ.sig, denomᵢ.pub)
    651   coinᵢ.h_denom = h_denomᵢ
    652   coinᵢ.blind_secret = blind_secretᵢ  // todo: why save blind_secret, if batch_seed already persisted?
    653 Persist ⟨coinᵢ⟩
    654 ]]></artwork>
    655         </section>
    656         <section anchor="withdraw-recoup">
    657           <name>Recoup</name>
    658           <t>// todo</t>
    659         </section>
    660       </section>
    661       <section anchor="payment-with-e-cash">
    662         <name>Payment with E-Cash</name>
    663         <section anchor="payment">
    664           <name>Payment and Deposit</name>
    665           <t>The wallet obtains <tt>contract</tt> information for an <tt>order</tt> from the merchant
    666 after claiming it with a <tt>nonce</tt>.
    667 Payment of the order is prepared by signing (partial) deposit authorizations <tt>⟨depositᵢ⟩</tt> with coins <tt>⟨coinᵢ⟩</tt> of certain denominations <tt>⟨denomᵢ⟩</tt>,
    668 where the sum of all contributions (<tt>contributionᵢ &lt;= denomᵢ.value</tt>) must match the <tt>contract.price</tt> plus potential deposit fees.
    669 The payment is complete as soon as the merchant successfully redeems the deposit authorizations at the exchange.</t>
    670           <t>Deposit could also be used directly by a wallet with its own payto and a minimal contract.</t>
    671           <artwork><![CDATA[
    672       wallet                        merchant                       exchange
    673 Knows ⟨coinᵢ⟩                  Knows merchant.priv         Knows exchange.priv
    674         |                      Knows exchange, payto       Knows ⟨denomᵢ⟩
    675         |                              |                              |
    676         |                 +-----------------------+                   |
    677         |                 | (M1) order generation |                   |
    678         |                 +-----------------------+                   |
    679         |                              |                              |
    680         |<--- (QR-Code / NFC / URI) ---|                              |
    681         |      (order.{id,token?})     |                              |
    682         |                              |                              |
    683 +-----------------------+              |                              |
    684 | (W1) nonce generation |              |                              |
    685 +-----------------------+              |                              |
    686         |                              |                              |
    687         |-- /orders/{order.id}/claim ->|                              |
    688         |  (nonce.pub, order.token?)   |                              |
    689         |                              |                              |
    690         |                 +--------------------------+                |
    691         |                 | (M2) contract generation |                |
    692         |                 +--------------------------+                |
    693         |                              |                              |
    694         |<-- (contract, merchant.pub, -|                              |
    695         |            sig)              |                              |
    696         |                              |                              |
    697 +--------------------------+           |                              |
    698 | (W2) payment preparation |           |                              |
    699 +--------------------------+           |                              |
    700         |                              |                              |
    701         |--- /orders/{order.id}/pay -->|                              |
    702         |         (⟨depositᵢ⟩)         |                              |
    703         |                              |                              |
    704         |                 +--------------------------+                |
    705         |                 | (M3) deposit preparation |                |
    706         |                 +--------------------------+                |
    707         |                              |                              |
    708         |                              |-------- /batch-deposit ----->|
    709         |                              | (info, h_contract, ⟨depositᵢ⟩|
    710         |                              |        merchant.pub, sig)    |
    711         |                              |                              |
    712         |                              |                  +--------------------+
    713         |                              |                  | (E1) deposit check |
    714         |                              |                  +--------------------+
    715         |                              |                              |
    716         |                              |<- (timestamp, exchange.pub, -|
    717         |                              |        sig)                  |
    718         |                              |                              |
    719         |                 +---------------------------+               |
    720         |                 | (M4) deposit verification |               |
    721         |                 +---------------------------+               |
    722         |                              |                              |
    723         |<----------- (sig) -----------|                              |
    724         |                              |                              |
    725 +---------------------------+          |                              |
    726 | (W3) payment verification |          |                              |
    727 +---------------------------+          |                              |
    728         |                              |                              |
    729 ]]></artwork>
    730           <t>where (without age restriction, policy and wallet data hash)</t>
    731           <artwork><![CDATA[
    732 (M1) order generation (merchant)
    733 
    734 wire_salt = random(128)
    735 determine id, price, info, token?
    736 Persist order = (id, price, info, token?, wire_salt)
    737 ]]></artwork>
    738           <artwork><![CDATA[
    739 (W1) nonce generation (wallet)
    740 
    741 nonce = Ed25519-Keygen()
    742 Persist nonce.priv
    743 ]]></artwork>
    744           <t>Note that the private key of <tt>nonce</tt> is currently not used anywhere in the protocol.
    745 However, it could be used in the future to prove ownership of an order transaction,
    746 enabling use-cases such as "unclaiming" or transferring an order to another person,
    747 or proving the payment without resorting to the individual coins.</t>
    748           <artwork><![CDATA[
    749 (M2) contract generation (merchant)
    750 
    751 Check order.token? == token?
    752 h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
    753 determine timestamp, refund_deadline, wire_deadline
    754 contract = (order.{id,price,info,token?}, exchange, h_wire, timestamp, refund_deadline, wire_deadline)
    755 contract.nonce = nonce.pub
    756 Persist contract
    757 h_contract = SHA-512(canonicalJSON(contract))
    758 msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
    759 sig = Ed25519-Sign(merchant.priv, msg)
    760 ]]></artwork>
    761           <artwork><![CDATA[
    762 (W2) payment preparation (wallet)
    763 
    764 h_contract = SHA-512(canonicalJSON(contract))
    765 msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
    766 Check Ed25519-Verify(merchant.pub, msg, sig)
    767 Check contract.nonce == nonce
    768 // TODO: double-check extra hash check?
    769 // todo: maybe get rid of CoinSelection altogether by claiming we already know coinᵢ and contributionᵢ
    770 ⟨selectionᵢ⟩ = CoinSelection(contract.{exchange,price}) TODO: include MarkDirty here
    771 for i in 0..n:
    772   (coinᵢ, denomᵢ, contributionᵢ) = selectionᵢ
    773   msgᵢ = Gen-Msg(WALLET_COIN_DEPOSIT,
    774       ( h_contract | uint256(0x0)
    775       | uint512(0x0) | contract.h_wire | coinᵢ.h_denom
    776       | contract.timestamp | contract.refund_deadline
    777       | contributionᵢ + denomᵢ.fee_deposit
    778       | denomᵢ.fee_deposit | merchant.pub | uint512(0x0) ))
    779   sigᵢ = Ed25519-Sign(coinᵢ.priv, msgᵢ)
    780   depositᵢ = (coinᵢ.{pub,sig,h_denom}, contributionᵢ, sigᵢ)
    781 Persist (contract, ⟨sigᵢ⟩, ⟨depositᵢ⟩)
    782 ]]></artwork>
    783           <t>// TODO: explain CoinSelection</t>
    784           <artwork><![CDATA[
    785 (M3) deposit preparation (merchant)
    786 
    787 Check Sum ⟨depositᵢ.contribution⟩ == contract.price
    788 info.time = contract.{timestamp, wire_deadline, refund_deadline}
    789 info.wire = (payto, wire_salt)
    790 h_contract = SHA-512(canonicalJSON(contract))
    791 msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
    792 sig = Ed25519-Sign(merchant.priv, msg)
    793 ]]></artwork>
    794           <artwork><![CDATA[
    795 (E1) deposit check (exchange)
    796 
    797 h_wire = HKDF(info.wire.wire_salt, info.wire.payto, "merchant-wire-signature", 64)
    798 for i in 0..n:
    799   coinᵢ = depositᵢ.coin
    800   denomᵢ = Lookup by coinᵢ.h_denom
    801   Check denomᵢ known and not deposit-expired
    802   totalᵢ = depositᵢ.contribution + denomᵢ.fee_deposit
    803   msgᵢ = Gen-Msg(WALLET_COIN_DEPOSIT,
    804       ( h_contract | uint256(0x0)
    805       | uint512(0x0) | h_wire | coinᵢ.h_denom
    806       | info.time.timestamp | info.time.refund_deadline
    807       | totalᵢ
    808       | denomᵢ.fee_deposit | merchant.pub | uint512(0x0) ))
    809   Check Ed25519-Verify(coinᵢ.pub, msgᵢ, depositᵢ.sig)
    810   Check RSA-FDH-Verify(SHA-512(coinᵢ.pub), coinᵢ.sig, denomᵢ.pub)
    811   Check-Subtract(coinᵢ.value, total)
    812 Persist deposit-record
    813 schedule bank transfer to payto
    814 timestamp = now()
    815 msg = Gen-Msg(EXCHANGE_CONFIRM_DEPOSIT,
    816     ( h_contract | h_wire | uint512(0x0)
    817     | timestamp | info.time.wire_deadline
    818     | info.time.refund_deadline
    819     | Sum ⟨depositᵢ.contribution⟩
    820     | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
    821 sig = Ed25519-Sign(exchange.priv, msg)
    822 ]]></artwork>
    823           <artwork><![CDATA[
    824 (M2) deposit verification (merchant)
    825 
    826 h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
    827 msg = Gen-Msg(EXCHANGE_CONFIRM_DEPOSIT,
    828     ( h_contract | h_wire | uint512(0x0)
    829     | timestamp | contract.wire_deadline
    830     | contract.refund_deadline
    831     | Sum ⟨depositᵢ.contribution⟩
    832     | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
    833 Check Ed25519-Verify(exchange.pub, msg, sig)
    834 msg = Gen-Msg(MERCHANT_PAYMENT_OK, h_contract)
    835 sig = Ed25519-Sign(merchant.priv, msg)
    836 ]]></artwork>
    837           <artwork><![CDATA[
    838 (W3) payment verification (wallet)
    839 
    840 msg = Gen-Msg(MERCHANT_PAYMENT_OK, h_contract)
    841 Check Ed25519-Verify(merchant.pub, msg, sig)
    842 ]]></artwork>
    843         </section>
    844         <section anchor="refund">
    845           <name>Refund</name>
    846           <t>A wallet can request a refund for an order from the merchant after it has been completed successfully
    847 (cf. <xref target="payment"/>) and before the merchant has been paid out by the exchange (i.e., before <tt>contract.wire_deadline</tt>).
    848 The merchant needs to approve the refund via its business logic,
    849 and is free to decide the total amount of the refund
    850 as well as which coins' deposit operations are (potentially partly) invalidated.
    851 After the exchange has accepted the refund request,
    852 the coins obtain their (partial) value back.
    853 The wallet should proceed to refresh (cf. <xref target="refresh"/>) the coins before spending them again
    854 to obtain unlinkability.</t>
    855           <t>In case the wallet itself has used deposit to its own payto,
    856 it can act as the merchant in the protocol below.</t>
    857           <t>// todo: if proves practical, similar strucuture could be used for pay/deposit
    858 (interaction) between wallet, merchant and exchange</t>
    859           <artwork><![CDATA[
    860       wallet                        merchant                       exchange
    861 Knows order.id                 Knows merchant.priv         Knows deposit_record
    862 Knows contract                         |                         for coinᵢ.pub
    863         |                              |                              |
    864 +---------------------+                |                              |
    865 | (W1) refund request |                |                              |
    866 +---------------------+                |                              |
    867         |                              |                              |
    868         |- /orders/{order.id}/refund ->|                              |
    869         |          (h_contract)        |                              |
    870         |                              |                              |
    871         |                 +------------------------+                  |
    872         |                 | (M1) refund processing |                  |
    873         |                 +------------------------+                  |
    874         |                              |                              |
    875         |                              |- /coins/{coinᵢ.pub}/refund ->|
    876         |                              |   (valueᵢ, h_contract, id,   |
    877         |                              |      merchant.pub, sigᵢ)     |
    878         |                              |                              |
    879         |                              |                  +-------------------+
    880         |                              |                  | (E1) refund check |
    881         |                              |                  +-------------------+
    882         |                              |                              |
    883         |                              |<--- (exchange.pub, sigᵢ) ----|
    884         |                              |                              |
    885         |                 +--------------------------+                |
    886         |                 | (M2) refund confirmation |                |
    887         |                 +--------------------------+                |
    888         |                              |                              |
    889         |<-----(value, ⟨refundᵢ⟩,------|                              |
    890         |        merchant.pub)         |                              | // todo: why merchant.pub if no sig transmitted?
    891         |                              |                              |
    892 +-----------------------+              |                              |
    893 | (W2) refund reception |              |                              |
    894 +-----------------------+              |                              |
    895         |                              |                              |
    896 ]]></artwork>
    897           <t>where (for RSA, without age-restriction)</t>
    898           <artwork><![CDATA[
    899 (W1) refund request (wallet)
    900 
    901 h_contract = SHA-512(canonicalJSON(contract))
    902 ]]></artwork>
    903           <artwork><![CDATA[
    904 (M1) refund processing (merchant)
    905 
    906 Check h_contract known and refund possible
    907 time = now()
    908 ⟨coinᵢ⟩ = Lookup by h_contract
    909 id = ?
    910 for i in 0..n:
    911   denomᵢ = Lookup by coinᵢ.h_denom
    912   valueᵢ = refund amount // todo: split wisely
    913   msgᵢ = Gen-Msg(MERCHANT_REFUND,
    914        ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
    915   sigᵢ = Ed25519-Sign(merchant.priv, msgᵢ)
    916 ]]></artwork>
    917           <artwork><![CDATA[
    918 (E1) refund check and confirmation (exchange)
    919 
    920 deposit_record = Lookup by h_contract // todo: needs to be persisted before with order.id and used coins!
    921 Check coinᵢ.pub part of deposit_record
    922 denomᵢ = Lookup by coinᵢ.pub
    923 msgᵢ = Gen-Msg(MERCHANT_REFUND,
    924     ( h_contract | coinᵢ.pub | id | valueᵢ | denomᵢ.fee_refund ))
    925 Check Ed25519-Verify(merchant.pub, msgᵢ, sigᵢ)
    926 Check valueᵢ >= denomᵢ.fee_refund
    927 Check refund possible (prior to wire transfer deadline)
    928 remove/update scheduled wire transfer
    929 mark coin part as unspent
    930 msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
    931 sigᵢ = Ed25519-Sign(exchange.priv, msgᵢ)
    932 ]]></artwork>
    933           <artwork><![CDATA[
    934 (M2) refund confirmation (merchant)
    935 
    936 for i in 0..n:
    937   msgᵢ = Gen-Msg(MERCHANT_REFUND_OK, SHA-512(order.id)) // todo: hashing string without terminating \0
    938   Check Ed25519-Verify(exchange.pub, msgᵢ, sigᵢ)
    939   update business logic
    940   refundᵢ = (valueᵢ, sigᵢ, id, coinᵢ.pub, time)
    941 value = sum ⟨valueᵢ⟩
    942 ]]></artwork>
    943           <artwork><![CDATA[
    944 (W2) refund reception (wallet)
    945 
    946 for i in 0..n:
    947   (valueᵢ, sigᵢ, id, coinᵢ.pub, time) = refundᵢ
    948 update persistent transaction information
    949 refresh ⟨coinᵢ⟩
    950 ]]></artwork>
    951         </section>
    952       </section>
    953       <section anchor="obtaining-unlinkable-change">
    954         <name>Obtaining unlinkable change</name>
    955         <section anchor="refresh">
    956           <name>Refresh</name>
    957           <t>The wallet obtains <tt>n</tt> new coins <tt>⟨coinᵢ⟩</tt> of denominations <tt>⟨denomᵢ⟩</tt>
    958 in exchange for one old <tt>coin</tt> of denomination <tt>denom</tt> from the exchange.
    959 There are three reasons why a wallet needs to do this:</t>
    960           <ol spacing="normal" type="1"><li>
    961               <t>Obtaining unlinkable change after using only a part of the coin's value during a payment (cf. <xref target="payment"/>),
    962 i.e. where <tt>contribution &lt;= denom.value</tt></t>
    963             </li>
    964             <li>
    965               <t>Obtaining unlinkable change after a successful refund (cf. <xref target="refund"/>)</t>
    966             </li>
    967             <li>
    968               <t>Renewing a coin before it deposit-expires</t>
    969             </li>
    970           </ol>
    971           <t>The sum of the refresh fee of <tt>denom</tt> and the new denominations' values and withdrawal fees (defined by the exchange)
    972 must be smaller or equal to the residual value of the old <tt>coin</tt>.</t>
    973           <t>The private key of each new coin candidate <tt>⟨coinₖᵢ.priv⟩</tt> is transitively derived from the old coin's private key <tt>coin.priv</tt>
    974 via a 512-bit secret <tt>⟨sharedₖᵢ⟩</tt> according to <tt>Refresh-Derive</tt>.
    975 The secret is regeneratable with the knowledge of <tt>coin.priv</tt> via the link protocol (cf. <xref target="link"/>).
    976 The derivation ensures that ownership of coins (knowledge of the private key) is correctly transferred,
    977 and thereby that value transfer among untrusted parties can only happen via payment and deposit, not via refresh.</t>
    978           <artwork><![CDATA[
    979 Refresh-Derive(shared, denom) =
    980   planchet_seed = HKDF(uint32(i), shared, "taler-coin-derivation", 64)
    981   blind_secret = HKDF("bks", planchet_seed, "", 32)
    982   coin.priv = HKDF("coin", planchet_seed, "", 32)
    983   coin.pub = Ed25519-GetPub(coin.priv)
    984   planchet = RSA-FDH-Blind(SHA-512(coin.pub), blind_secret, denomᵢ.pub)
    985   h_planchet = Hash-Planchet(planchet, denomᵢ)
    986   return (coin, blind_secret, planchet, h_planchet)
    987 ]]></artwork>
    988           <t>Taler uses a cut-and-choose protocol with the fixed parameter <tt>κ=3</tt> to enforce correct derivation
    989 of <tt>⟨sharedₖᵢ⟩</tt> from a single seed per batch of planchets <tt>⟨batch_seedₖ⟩</tt>
    990 (in (κ-1)/κ of the cases, making income concealment for tax evasion purposes unpractical).</t>
    991           <t>Refreshing consists of two parts:</t>
    992           <ol spacing="normal" type="1"><li>
    993               <t>Melting of the old coin and commiting to κ batches of blinded planchet candidates</t>
    994             </li>
    995             <li>
    996               <t>Revelation of κ-1 secrets <tt>⟨revealed_seedₖ⟩</tt> to prove the proper construction of the (revealed) batches of blinded planchet candidates.</t>
    997             </li>
    998           </ol>
    999           <artwork><![CDATA[
   1000             wallet                                  exchange
   1001 Knows ⟨denomᵢ⟩                          Knows ⟨denomᵢ.priv⟩
   1002 Knows coin                                              |
   1003                |                                        |
   1004 +-------------------+                                   |
   1005 | (W1) coin melting |                                   |
   1006 +-------------------+                                   |
   1007                |                                        |
   1008                |---------------- /melt ---------------->|
   1009                |     (coin.{pub,sig,h_denom}, value,    |
   1010                |      refresh_seed, planchets, sig)     |
   1011                |                                        |
   1012                |                      +---------------------------------------+
   1013                |                      | (E1) gamma selection and coin signing |
   1014                |                      +---------------------------------------+
   1015                |                                        |
   1016                |<------ (ɣ, exchange.pub, sig) ---------|
   1017                |                                        |
   1018 +------------------------+                              |
   1019 | (W2) secret revelation |                              |
   1020 +------------------------+                              |
   1021                |                                        |
   1022                |------------ /reveal-melt ------------->|
   1023                |     (commitment, ⟨revealed_seedₖ⟩)     |
   1024                |                                        |
   1025                |                      +----------------------------+
   1026                |                      | (E2) commitment validation |
   1027                |                      +----------------------------+
   1028                |                                        |
   1029                |<---------- (⟨blind_sigᵢ⟩) -------------|
   1030                |                                        |
   1031 +----------------------+                                |
   1032 | (W3) coin unblinding |                                |
   1033 +----------------------+                                |
   1034                |                                        |
   1035 ]]></artwork>
   1036           <t>where (for RSA, without age-restriction)</t>
   1037           <artwork><![CDATA[
   1038 (W1) coin melting (wallet)
   1039 
   1040 refresh_seed = random(256)
   1041 ⟨batch_seedₖ⟩ = HKDF("refresh-batch-seeds", refresh_seed, coin.priv, k*64)
   1042 for k in 0..κ:
   1043   ⟨transferₖᵢ.priv⟩ = HKDF("refresh-transfer-private-keys", batch_seedₖ, "", n*32)
   1044   for i in 0..n:
   1045     transferₖᵢ.pub = ECDH-GetPub(transferₖᵢ.priv)
   1046     sharedₖᵢ = ECDH-Ed25519-Pub(transferₖᵢ.priv, coin.pub)
   1047     (coinₖᵢ, blind_secretₖᵢ, planchetₖᵢ, h_planchetₖᵢ) = Refresh-Derive(sharedₖᵢ, denomᵢ)
   1048   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
   1049 value = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
   1050 commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
   1051                     | SHA-512( ⟨h_planchetsₖ⟩ ) )
   1052 for i in 0..n:
   1053   h_denomᵢ = Hash-Denom(denomᵢ)
   1054 planchets = (⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩))
   1055 msg = Gen-Msg(WALLET_COIN_MELT,
   1056     ( commitment | coin.h_denom | uint256(0x0)
   1057     | value | denom.fee_refresh ))
   1058 sig = Ed25519-Sign(coin.priv, msg)
   1059 Persist (coin.denom.pub, ...) // todo: double-check
   1060 ]]></artwork>
   1061           <artwork><![CDATA[
   1062 (E1) gamma selection and coin signing (exchange)
   1063 
   1064 denom = Lookup by coin.h_denom
   1065 Check denom known and not deposit-expired
   1066 Check RSA-FDH-Verify(SHA-512(coin.pub), coin.sig, denom.pub)
   1067 Check coin.pub known and dirty
   1068 (⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩)) = planchets
   1069 for i in 0..n:
   1070   denomᵢ = Lookup by h_denomᵢ
   1071   Check denomᵢ known and not withdraw-expired
   1072 value' = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
   1073 Check value' == value
   1074 Check-Subtract(coin.value, value)
   1075 for k in 0..κ:
   1076   for i in 0..n:
   1077     h_planchetₖᵢ = Hash-Planchet(planchetₖᵢ, denomᵢ)
   1078   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
   1079 commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
   1080                     | SHA-512( ⟨h_planchetsₖ⟩ ) )
   1081 msg = Gen-Msg(WALLET_COIN_MELT,
   1082     ( commitment | coin.h_denom | uint256(0x0)
   1083     | value | denom.fee_refresh ))
   1084 Check Ed25519-Verify(coin.pub, msg, sig)
   1085 refresh_record = Lookup by commitment
   1086 (ɣ, _, _, done, _) = refresh_record
   1087 if refresh_record not found:
   1088   ɣ = 0..κ at random
   1089   for i in 0..n:
   1090     blind_sigᵢ = RSA-FDH-Sign(planchetᵧᵢ, denomᵧᵢ.priv)
   1091   link_info = (refresh_seed, ⟨transferₖᵢ.pub⟩, ⟨h_denomᵢ⟩, coin_sig)
   1092   Persist refresh_record = (commitment, ɣ, ⟨blind_sigᵢ⟩, h_planchetsᵧ, false, link_info)
   1093 msg = Gen-Msg(EXCHANGE_CONFIRM_MELT,
   1094     ( commitment | uint32(ɣ) ))
   1095 sig = Ed25519-Sign(exchange.priv, msg)
   1096 ]]></artwork>
   1097           <artwork><![CDATA[
   1098 (W2) secret revelation (wallet)
   1099 
   1100 Check exchange.pub known
   1101 msg = Gen-Msg(EXCHANGE_CONFIRM_MELT,
   1102     ( commitment | ɣ ))
   1103 Check Ed25519-Verify(exchange.pub, msg, sig)
   1104 Persist refresh-challenge // what exactly?
   1105 for k in 0..κ and k != ɣ:
   1106   revealed_seedₖ = batch_seedₖ
   1107 ]]></artwork>
   1108           <artwork><![CDATA[
   1109 (E2) commitment validation (exchange)
   1110 
   1111 refresh_record = Lookup by commitment
   1112 (ɣ, ⟨blind_sigᵢ⟩, h_planchetsᵧ, done, _) = refresh_record
   1113 Check not done // todo: sure?
   1114 for k in 0..κ and k != ɣ:
   1115   ⟨transferₖᵢ.priv⟩ = HKDF("refresh-transfer-private-keys", batch_seedₖ, "", n*32)
   1116   for i in 0..n:
   1117     transferₖᵢ.pub = ECDH-GetPub(transferₖᵢ.priv)
   1118     sharedₖᵢ = ECDH-Ed25519-Pub(transferₖᵢ.priv, coin.pub)
   1119     (_, _, _, h_planchetₖᵢ) = Refresh-Derive(sharedₖᵢ, denomᵢ)
   1120   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
   1121 value = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
   1122 commitment' = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
   1123                      | SHA-512( ⟨h_planchetsₖ⟩ ) )
   1124 Check commitment == commitment'
   1125 Persist refresh_record = (_, _, _, true, _)
   1126 ]]></artwork>
   1127           <artwork><![CDATA[
   1128 (W3) coin unblinding (wallet)
   1129 
   1130 for i in 0..n:
   1131   coinᵧᵢ.sig = RSA-FDH-Unblind(blind_sigᵧᵢ, blind_secretᵧᵢ, denomᵢ.pub)
   1132   Check RSA-FDH-Verify(SHA-512(coinᵧᵢ.pub), coinᵧᵢ.sig, denomᵢ.pub)
   1133   coinᵧᵢ.h_denom = h_denomᵢ
   1134   Persist ⟨coinᵧᵢ⟩
   1135 ]]></artwork>
   1136         </section>
   1137         <section anchor="link">
   1138           <name>Link</name>
   1139           <t>Coins ⟨coinᵧᵢ⟩ obtained via the refresh protocol (cf. <xref target="refresh"/>) can be regenerated
   1140 with the knowledge of the old coin's private key <tt>coin.priv</tt> using the link protocol,
   1141 integrated in the coin history endpoint.</t>
   1142           <artwork><![CDATA[
   1143             wallet                                  exchange
   1144 Knows coin                              Knows refresh_record for coin.pub
   1145                |                                        |
   1146 +----------------------+                                |
   1147 | (W1) history request |                                |
   1148 +----------------------+                                |
   1149                |                                        |
   1150                |------ /coins/{coin.pub}/history ------>|
   1151                |                 (sig)                  |
   1152                |                                        |
   1153                |                      +----------------------------+
   1154                |                      | (E1) refresh secret lookup |
   1155                |                      +----------------------------+
   1156                |                                        |
   1157                |<------------- (melt_info) -------------|
   1158                |                                        |
   1159 +-----------------------+                               |
   1160 | (W2) coin acquisition |                               |
   1161 +-----------------------+                               |
   1162                |                                        |
   1163 ]]></artwork>
   1164           <t>where (for RSA, without age-restriction)</t>
   1165           <artwork><![CDATA[
   1166 (W1) history request (wallet)
   1167 
   1168 msg = Gen-Msg(COIN_HISTORY_REQUEST, uint64(0x0))
   1169 sig = Ed25519-Sign(coin.priv, msg)
   1170 ]]></artwork>
   1171           <artwork><![CDATA[
   1172 (E1) refresh secret lookup (exchange)
   1173 
   1174 refresh_record = Lookup by coin.pub
   1175 (ɣ, ⟨blind_sigᵢ⟩, _, done, link_info) = refresh_record
   1176 if done:
   1177   melt_info = (ɣ, link_info, ⟨blind_sigᵢ⟩)
   1178 else:
   1179   melt_info = (ɣ, link_info)
   1180 ]]></artwork>
   1181           <artwork><![CDATA[
   1182 (W2) coin acquisition (wallet)
   1183 
   1184 (ɣ, link_info, ⟨blind_sigᵢ⟩?) = melt_info
   1185 (refresh_seed, ⟨transferₖᵢ.pub⟩, ⟨h_denomᵢ⟩, coin_sig) = link_info
   1186 
   1187 for i in 0..n:
   1188   denomᵢ = Lookup by h_denomᵢ
   1189 for k in 0..κ:
   1190   for i in 0..n:
   1191     sharedₖᵢ = ECDH-Ed25519-Priv(coin.priv, transferₖᵢ.pub)
   1192     (coinₖᵢ, blind_secretₖᵢ _, h_planchetₖᵢ) = Refresh-Derive(sharedₖᵢ, denomᵢ)
   1193   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
   1194 value = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
   1195 commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
   1196                     | SHA-512( ⟨h_planchetsₖ⟩ ) )
   1197 msg = Gen-Msg(WALLET_COIN_MELT,
   1198     ( commitment | coin.h_denom | uint256(0x0)
   1199     | value | denom.fee_refresh ))
   1200 Check Ed25519-Verify(coin.pub, msg, sig)
   1201 
   1202 if ⟨blind_sigᵢ⟩ returned:
   1203   for i in 0..n:
   1204     coinᵧᵢ.sig = RSA-FDH-Unblind(blind_sigᵧᵢ, blind_secretᵧᵢ, denomᵢ.pub)
   1205     Check RSA-FDH-Verify(SHA-512(coinᵧᵢ.pub), coinᵧᵢ.sig, denomᵢ.pub)
   1206     coinᵧᵢ.h_denom = h_denomᵢ
   1207   Persist ⟨coinᵧᵢ⟩
   1208 ]]></artwork>
   1209         </section>
   1210         <section anchor="refresh-recoup">
   1211           <name>Recoup</name>
   1212           <t>// todo</t>
   1213         </section>
   1214       </section>
   1215       <section anchor="w2w">
   1216         <name>Transfer of E-Cash</name>
   1217         <t>// todo: introductory text</t>
   1218         <t>Transactions in E-Cash between wallets.
   1219 Commonly referred to as peer-to-peer transactions.
   1220 In Taler, interaction with exchange, therefore called wallet-to-wallet transactions.</t>
   1221         <section anchor="w2w-account">
   1222           <name>Account Creation</name>
   1223         </section>
   1224         <section anchor="w2w-push">
   1225           <name>Push Payment</name>
   1226           <t>// todo</t>
   1227         </section>
   1228         <section anchor="w2w-pull">
   1229           <name>Pull Payment</name>
   1230           <t>// todo</t>
   1231         </section>
   1232       </section>
   1233     </section>
   1234     <section anchor="security-considerations">
   1235       <name>Security Considerations</name>
   1236       <t>[ TBD ]</t>
   1237     </section>
   1238     <section anchor="iana-considerations">
   1239       <name>IANA Considerations</name>
   1240       <t>None.</t>
   1241     </section>
   1242   </middle>
   1243   <back>
   1244     <references anchor="sec-normative-references">
   1245       <name>Normative References</name>
   1246       <reference anchor="RFC20">
   1247         <front>
   1248           <title>ASCII format for network interchange</title>
   1249           <author fullname="V.G. Cerf" initials="V.G." surname="Cerf"/>
   1250           <date month="October" year="1969"/>
   1251         </front>
   1252         <seriesInfo name="STD" value="80"/>
   1253         <seriesInfo name="RFC" value="20"/>
   1254         <seriesInfo name="DOI" value="10.17487/RFC0020"/>
   1255       </reference>
   1256       <reference anchor="RFC2104">
   1257         <front>
   1258           <title>HMAC: Keyed-Hashing for Message Authentication</title>
   1259           <author fullname="H. Krawczyk" initials="H." surname="Krawczyk"/>
   1260           <author fullname="M. Bellare" initials="M." surname="Bellare"/>
   1261           <author fullname="R. Canetti" initials="R." surname="Canetti"/>
   1262           <date month="February" year="1997"/>
   1263           <abstract>
   1264             <t>This document describes HMAC, a mechanism for message authentication using cryptographic hash functions. HMAC can be used with any iterative cryptographic hash function, e.g., MD5, SHA-1, in combination with a secret shared key. The cryptographic strength of HMAC depends on the properties of the underlying hash function. This memo provides information for the Internet community. This memo does not specify an Internet standard of any kind</t>
   1265           </abstract>
   1266         </front>
   1267         <seriesInfo name="RFC" value="2104"/>
   1268         <seriesInfo name="DOI" value="10.17487/RFC2104"/>
   1269       </reference>
   1270       <reference anchor="RFC5869">
   1271         <front>
   1272           <title>HMAC-based Extract-and-Expand Key Derivation Function (HKDF)</title>
   1273           <author fullname="H. Krawczyk" initials="H." surname="Krawczyk"/>
   1274           <author fullname="P. Eronen" initials="P." surname="Eronen"/>
   1275           <date month="May" year="2010"/>
   1276           <abstract>
   1277             <t>This document specifies a simple Hashed Message Authentication Code (HMAC)-based key derivation function (HKDF), which can be used as a building block in various protocols and applications. The key derivation function (KDF) is intended to support a wide range of applications and requirements, and is conservative in its use of cryptographic hash functions. This document is not an Internet Standards Track specification; it is published for informational purposes.</t>
   1278           </abstract>
   1279         </front>
   1280         <seriesInfo name="RFC" value="5869"/>
   1281         <seriesInfo name="DOI" value="10.17487/RFC5869"/>
   1282       </reference>
   1283       <reference anchor="RFC6234">
   1284         <front>
   1285           <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
   1286           <author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake 3rd"/>
   1287           <author fullname="T. Hansen" initials="T." surname="Hansen"/>
   1288           <date month="May" year="2011"/>
   1289           <abstract>
   1290             <t>Federal Information Processing Standard, FIPS</t>
   1291           </abstract>
   1292         </front>
   1293         <seriesInfo name="RFC" value="6234"/>
   1294         <seriesInfo name="DOI" value="10.17487/RFC6234"/>
   1295       </reference>
   1296       <reference anchor="RFC7748">
   1297         <front>
   1298           <title>Elliptic Curves for Security</title>
   1299           <author fullname="A. Langley" initials="A." surname="Langley"/>
   1300           <author fullname="M. Hamburg" initials="M." surname="Hamburg"/>
   1301           <author fullname="S. Turner" initials="S." surname="Turner"/>
   1302           <date month="January" year="2016"/>
   1303           <abstract>
   1304             <t>This memo specifies two elliptic curves over prime fields that offer a high level of practical security in cryptographic applications, including Transport Layer Security (TLS). These curves are intended to operate at the ~128-bit and ~224-bit security level, respectively, and are generated deterministically based on a list of required properties.</t>
   1305           </abstract>
   1306         </front>
   1307         <seriesInfo name="RFC" value="7748"/>
   1308         <seriesInfo name="DOI" value="10.17487/RFC7748"/>
   1309       </reference>
   1310       <reference anchor="RFC8032">
   1311         <front>
   1312           <title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
   1313           <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
   1314           <author fullname="I. Liusvaara" initials="I." surname="Liusvaara"/>
   1315           <date month="January" year="2017"/>
   1316           <abstract>
   1317             <t>This document describes elliptic curve signature scheme Edwards-curve Digital Signature Algorithm (EdDSA). The algorithm is instantiated with recommended parameters for the edwards25519 and edwards448 curves. An example implementation and test vectors are provided.</t>
   1318           </abstract>
   1319         </front>
   1320         <seriesInfo name="RFC" value="8032"/>
   1321         <seriesInfo name="DOI" value="10.17487/RFC8032"/>
   1322       </reference>
   1323       <reference anchor="HKDF">
   1324         <front>
   1325           <title>Cryptographic Extraction and Key Derivation: The HKDF Scheme</title>
   1326           <author fullname="Hugo Krawczyk" initials="H." surname="Krawczyk">
   1327             <organization/>
   1328           </author>
   1329           <date year="2010"/>
   1330         </front>
   1331         <seriesInfo name="Lecture Notes in Computer Science" value="pp. 631-648"/>
   1332         <seriesInfo name="DOI" value="10.1007/978-3-642-14623-7_34"/>
   1333         <seriesInfo name="ISBN" value="[&quot;9783642146220&quot;, &quot;9783642146237&quot;]"/>
   1334         <refcontent>Springer Berlin Heidelberg</refcontent>
   1335       </reference>
   1336       <reference anchor="SHS">
   1337         <front>
   1338           <title>Secure hash standard</title>
   1339           <author>
   1340             <organization/>
   1341           </author>
   1342           <date year="2015"/>
   1343         </front>
   1344         <seriesInfo name="DOI" value="10.6028/nist.fips.180-4"/>
   1345         <refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
   1346       </reference>
   1347     </references>
   1348     <?line 1386?>
   1349 
   1350 <section anchor="test-vectors">
   1351       <name>Test Vectors</name>
   1352       <t>This appendix provides two sets of test vectors for testing Taler Protocol implementations.
   1353 They are generated by going through the protocol operations in the following order:</t>
   1354       <ol spacing="normal" type="1"><li>
   1355           <t>Withdraw two coins <tt>coin₀</tt> and <tt>coin₁</tt> from a single <tt>reserve</tt> (cf. <xref target="withdraw"/>).</t>
   1356         </li>
   1357         <li>
   1358           <t>Pay for one <tt>order</tt> with the full value of <tt>coin₀</tt> and a partial value of <tt>coin₁</tt> (cf. <xref target="payment"/>).</t>
   1359         </li>
   1360         <li>
   1361           <t>Obtain a partial refund for <tt>coin₀</tt> used to pay for the <tt>order</tt> (cf. <xref target="refund"/>).</t>
   1362         </li>
   1363         <li>
   1364           <t>Refresh the now-dirty <tt>coin₁</tt> to two new coins <tt>coin₂</tt> and <tt>coin₃</tt> (cf. <xref target="refresh"/>).</t>
   1365         </li>
   1366         <li>
   1367           <t>Regenerate <tt>coin₂</tt> and <tt>coin₃</tt> with the knowledge of <tt>coin₁</tt> (cf. <xref target="link"/>).</t>
   1368         </li>
   1369         <li>
   1370           <t>Create an <tt>account</tt> for w2w transfers (cf. <xref target="w2w-account"/>).</t>
   1371         </li>
   1372         <li>
   1373           <t>Send a payment to <tt>account</tt> with the full value of <tt>coin₂</tt>, obtaining <tt>coin₅</tt> (cf. <xref target="w2w-push"/>).</t>
   1374         </li>
   1375         <li>
   1376           <t>Request a payment to <tt>account</tt>, which is paid with the full value of <tt>coin₅</tt>, obtaining <tt>coin₆</tt> (cf. <xref target="w2w-pull"/>).</t>
   1377         </li>
   1378         <li>
   1379           <t>Recoup the value of <tt>coin₆</tt> obtained via withdrawal from <tt>account</tt> (cf. <xref target="withdraw-recoup"/>).</t>
   1380         </li>
   1381         <li>
   1382           <t>Recoup the value of <tt>coin₃</tt> obtained via refresh from <tt>coin₁</tt> (cf. <xref target="refresh-recoup"/>).</t>
   1383         </li>
   1384       </ol>
   1385       <t>The test vectors in this document have been generated by the GNU Taler reference implementation written in C.
   1386 All binary data is provided in hexadecimal notation.</t>
   1387       <section anchor="test-case-1">
   1388         <name>Test Case 1</name>
   1389         <artwork><![CDATA[
   1390 denom₀.priv = XXX
   1391 denom₀.pub = XXX
   1392 denom₀.value = XXX
   1393 denom₀.fee_withdraw = XXX
   1394 denom₁.priv = XXX
   1395 denom₁.pub = XXX
   1396 denom₁.value = XXX
   1397 denom₁.fee_withdraw = XXX
   1398 ]]></artwork>
   1399         <section anchor="tc1-withdraw">
   1400           <name>Withdrawal</name>
   1401           <artwork><![CDATA[
   1402 (W1) reserve key generation (wallet)
   1403 
   1404 reserve.priv = XXX
   1405 reserve.pub = XXX
   1406 reserve.balance = XXX
   1407 ]]></artwork>
   1408           <artwork><![CDATA[
   1409 (W2) coin generation and blinding (wallet)
   1410 
   1411 batch_seed = XXX
   1412 coin_seed₀ = XXX
   1413 coin_seed₁ = XXX
   1414 blind_secret₀ = XXX
   1415 blind_secret₁ = XXX
   1416 coin₀.priv = XXX
   1417 coin₁.priv = XXX
   1418 coin₀.pub = XXX
   1419 coin₁.pub = XXX
   1420 h_denom₀ = XXX
   1421 h_denom₁ = XXX
   1422 planchet₀ = XXX
   1423 planchet₁ = XXX
   1424 h_planchet₀ = XXX
   1425 h_planchet₁ = XXX
   1426 msg = XXX
   1427 sig = XXX
   1428 ]]></artwork>
   1429           <artwork><![CDATA[
   1430 (E1) coin issuance and signing (exchange)
   1431 
   1432 total = XXX
   1433 blind_sig₀ = XXX
   1434 blind_sig₁ = XXX
   1435 ]]></artwork>
   1436           <artwork><![CDATA[
   1437 (W3) coin unblinding (wallet)
   1438 
   1439 coin₀.sig = XXX
   1440 coin₁.sig = XXX
   1441 ]]></artwork>
   1442         </section>
   1443         <section anchor="tc1-payment">
   1444           <name>Payment and Deposit</name>
   1445         </section>
   1446         <section anchor="tc1-refund">
   1447           <name>Refund</name>
   1448         </section>
   1449         <section anchor="tc1-refresh">
   1450           <name>Refresh</name>
   1451         </section>
   1452         <section anchor="tc1-link">
   1453           <name>Link</name>
   1454         </section>
   1455         <section anchor="tc1-w2w-account">
   1456           <name>Account Creation</name>
   1457         </section>
   1458         <section anchor="tc1-w2w-push">
   1459           <name>Push Payment</name>
   1460         </section>
   1461         <section anchor="tc1-w2w-pull">
   1462           <name>Pull Payment</name>
   1463         </section>
   1464         <section anchor="tc1-withdraw-recoup">
   1465           <name>Recoup Withdrawal</name>
   1466         </section>
   1467         <section anchor="tc1-refresh-recoup">
   1468           <name>Recoup Refresh</name>
   1469         </section>
   1470       </section>
   1471       <section anchor="test-case-2">
   1472         <name>Test Case 2</name>
   1473       </section>
   1474     </section>
   1475     <section anchor="change-log">
   1476       <name>Change log</name>
   1477     </section>
   1478     <section numbered="false" anchor="acknowledgments">
   1479       <name>Acknowledgments</name>
   1480       <t>[ TBD ]</t>
   1481       <t>This work was supported in part by the German Federal Ministry of
   1482 Education and Research (BMBF) within the project Concrete Contracts.</t>
   1483     </section>
   1484   </back>
   1485   <!-- ##markdown-source:
   1486 H4sIAAAAAAAAA+19y3bcRpbgHl8RJS2caeeDpGTZZpv20BRlqS1RapIq2+PS
   1487 ZCKBYCaKSCAbQJLMklSnXH16PmG2fc7UwjMf0Js6s5tVbeofqr9k7iMiEAEg
   1488 H5QolaumeXwsEojHjRs37jsuut2ud7Er7nheERWx3BW3TidSfH30XJz6sczE
   1489 sywt0iCNb3lhGiT+FFqEmX9WdMdzWeTBJL3sFtiwO1MNvcAv5DjNFrsiSs5S
   1490 z4tm2a4osnle7Gxtfba1412m2fk4S+czbBHKmYT/JYWXF5n0p+6zc7mA1uGu
   1491 J0RX0Dz0W5AtZkU6zvzZZEEPZODnE/pt5i+m0DP3vNsXMpnLXe+2EJmcpbti
   1492 UhSzfLffH0dFb5zME1n00mzcj/NwCwDrweM+No4B/rwom8P7huZ9z/PnxSTN
   1493 ALYuzCwEI+dJdJ7GfiS+/r//h9FD76Djrjh9fl/cz2QOKxPPk+hCZnlULER6
   1494 Jk5lMEnSOB0vqLU/GmXyAjvo9vQYESQBsIcynk7SuPgNPOiJ7S16GcBQu07z
   1495 IA0Bnvvdre2te5+pJ/OkwI35WmZTP+HJ5NSP4l0xZbh7Zlv/SzHvhjxcL5Se
   1496 l6TQpwCocTOOHxzsbOlftrfuql8//vTeZ+rXezt39NNPPrn7qfr10607O/jr
   1497 w2/uPwDYnj7qbW/Bf1uf9D/75NPune69uzvd7bvQt/vJ4M5daHjy8MS0u7e1
   1498 82n/6NHJae/Bo2cnve1Pt7p3gbyAyAxkntftdgF/gBk/KDzvVz+I06++Fb96
   1499 wS+mURjGsJbb4hEgIg3nQRGlidPsK3npZ1IUE7+A/0W5ALKfI0UJ+D0vojgW
   1500 SL/dKEGKHwOCcuEnoZj6C8BvUvhRImSWpVne857nUsAwi3SeifQyEVmUn/8C
   1501 Zz9KC59n7orhLX8U3BoKwHMKhAeTShFHhcz8GHc8SsZiCC2GQia4o6Hwc7F/
   1502 cvDokfiBduEFjuGLV2LkjgHA4ElMaCIkMl9cRsVEjLB9LJOW365MKpMxvAf4
   1503 Rwt8Bl3wMf6hAfGx78wP/6vM0taiI6pDOG074jfQrAvNEeoitSeBsRc8DY44
   1504 ioq8ddUe9of0CH91hp1GSTQFdCTz6QhYEnTGHn0GM5EB7IGfLXAKOOiwI7hb
   1505 1G8eF9EslgIeBlGOeIgSYE4wxhXOO4e/cBnV+YaLIQDq54XIo3ESnUWBDyPi
   1506 nBopepjh1dBdJpKC3ijAJDANpBZGDDAy6NIaRWNoEkZ+0tZAfE9LvpxIoLzh
   1507 90MkNV/MUmAPQNVmMrV8eCn/eR5dADfEdaZqHd/TOnDEDIBIp62FtSpf8MN4
   1508 IcYyAdoqAL4chgFYpdoNWB6T0odiJFrTNBRHMEKfnjiPnK1hFAOGiMz6Ql7N
   1509 0gQAiwzdLd8FhAsRNuoIGHsep+IIIYDzDFgdRmfw/ws/i/wRdPZz3As6iMM9
   1510 eIH9gMTDCKcB2khnuKoUx8Tjm4oRIy6DWXGxcXSOp1pGINIWwLeT/j/O48i3
   1511 UEmrD/3C74HUcVcJJx2GB149pFewAnyajn4tg4L7EOK3er3E7Sivgnie4yYC
   1512 /seEaXc3c3GWpVPoOqSdTGBlUU/2YPlbHbHdETsd0evBn0l3m6b4j3/7Xzjd
   1513 X/79f/7Hv/3vIZ1oIDOfWI+8KnCCYST2hAsKjKugzRlc6A8zmdPCxDqVUxDb
   1514 yF94vCiZp3PEZ+Yv3LkRQ9eZ3094FH18EB6F0wjBY6wCiwLu2ggrMs2DUuhH
   1515 Aegl0ZSOB0j6fh+QF4KEByYM2x5MCNfMvWUeZNGMaBEQnKdTiRCPgeCATHIY
   1516 I/YzfKPVF3E2T0gq5KJFFAKcPp9FGZ6XBbD3qzbAUgXmIWgf4oHuiA1ug+Ta
   1517 7+58fE+8vJ1PfPjltef99re/9dTj1jQft0X3CzFBxcV7lMzmxS7JY3iB/8CG
   1518 wCPYE+BtTDiKdT4Wn4ud/3ZvW6RBIVHPeTovTGccjQZR3cJoDLoM9j6LrvAU
   1519 8BgI72PQQvbEnR09DgLnDXEA4j9E4DQy9taLAdqATRMnUqHobg9o9GP83z38
   1520 Hx7Ke70d7PGD0gFe9Ep0fLy9w+iAXyx0wF9vi47tnY9vBh/37m6MD1xNHR87
   1521 iI8dxMcdjY+7K/BBWG2BdkzCOtSP2wZPXXrnYusmCOjGMFahoNMSTwp5QZoB
   1522 lwGpEOZaCziLMhjT9NRsoY7fUJ5FCXOnly8V4bzeZWQUcjqD+W0K8gj6PYGv
   1523 ftjavbP9goECfctW6VhWIEsIo7Mzw4TVSH1F6NbcP4Aa+gJ/YdkPfAckDs0F
   1524 omMuYUuRJzxRKNsHuwAloJKJB6AMKJ7w8Mn+AezsZOrrHcUnXURmC3hgRyAP
   1525 pV0FVMC+EN/ifXmo9iVwGA/BoDkW63cKie4+OQQCMxGB5DIA2Uh/ltThF0r1
   1526 0T2xJbF2Q1LIlIlbZ6AzoOLFXV06AjCE+lftaQUiPl/wmo5X4MfBPKYjUEG9
   1527 sjBeKCR/A9DelxnIbFpyhemiXYEIPg/PXjMt4nQw0pJuooU92mKe82xs80Yk
   1528 sYDvF76tyPygLJwXHiEaNDtFP6iUODsBBJVmRCyHV2SJECc4vJrhP3khZ7jI
   1529 fD7Go6WWiXC82PWG+G9X9RoiXCAFiUiAOoE4QWpfTiLQh3RDHLLaDgh4KFrB
   1530 WQ8ODdHa63ZPkRt0auV+XHTEo2+edMhC74jHRHJPv3miyCTnLcR2tIUzpWPR
   1531 A6J40fJFkiZdRUKsXPKr9j9Q5/InOoOmBQrYiwjUYpiUbSlJyquv7QVAMDBf
   1532 1KXBcsJ+AKDFx4BKSWwDiYBGGHv85ix1ANRaCKLZn5VqaT4DzRPUeGGMxTSp
   1533 QNkCHR91Rp/VeUWsDFub2j5WLUsTRtF2BTTcTsURK1N8vid2Pv74Q+B7e+LT
   1534 7XtbbffIPFULXjZuC6Z8rIZu17gt9q4dpLM0jtPLXHHMZ8ffwMw2hZW00Gbu
   1535 8ZAZqOa/LVsytj2cwwyAlNeCIS0qqg5Bws0WFQpsfVS7T9IQTG4fT59SqukE
   1536 O2yfDvPrDrNuw+uA7OZZQgcVoSLmjlQFdiIeYfgb1dIxKIjJKjvwyDoYCE3r
   1537 qCMq56P5cBzpXV0+uHOI/tqnaINj9B7O0fXo3dnMI4vkgTrQ5FNqBoxDMiQE
   1538 Qy+bEuHoX6McxXAMZu9IE5nPbjBk8yzIo9/gWSkIXkUNugXYMV6YCvgjignc
   1539 z8URw36lzkGVmYpXAq3x7XstNUa7w36O1lG7bVa9R41a5Pc4aqPhXvrnYNqP
   1540 9sS2PijiCAjkqziCnTgBA9gHqtfaxGEI3GT7M0AJSS2SAYfh/ZN9S3TB0uhQ
   1541 BvPsQlJzZAuqZ8dzZa1SY1Gh1/IOHXYgeh8lYuaDsYasJesoMRmmMOEAqHIA
   1542 ewbWNQCA3dTgM2CRmf4jKK4qc9GB1b411olZuCv/BHnHEAdqhO7Xsng2H7Vm
   1543 IMPpRM7mI0erwRf6X1i3nhmpyiU76CjUv0DYTjvWSeBFo06CluSohqnexxVc
   1544 OVDDimBBLYKYYO/gvJWDsAr0zSCGjkM6rQw8ukDeCPqOB9pFMKn7mEhrJ2EC
   1545 R1SJEwJ7T7GtFvD6toeQ7ommLTOM/zbRMYziIgofKgRpyyaPxi7P1XjSCND4
   1546 0njSlo+2XdgLhH4jGboYh2dC/ctHSosf3XW0oD9ZftjzMMKh33VI5F6VRAgP
   1547 vwQ2d7aoYYIftwCVhIoOAlnaBA4+FF0YfDB9VNHBCNBLW75+aN+sw4MJKjso
   1548 gbAb+SaBMKLQ6o3qLnZ3lXpl0wXpVGoTL0bTIpjI4JzMPAtHn9RxRPxgf5xJ
   1549 iUyCmd53DTwvjtHDE4gDZHLiPujkkew+lHE8BbnROjy4/7CN63N5YAPfu1fy
   1550 PYxZwGkYAQYyqTirOXUzP8pYxU8TpK/QLM/XwBILln6IL5RcJzHQ8+5TcItk
   1551 dYIuX+iWKScjUxkMqzYSWS7ikaxTzbMrdkdpcuChRzsGUPdydxeQjnC89nIp
   1552 y1BWNMrTMJpPMdg1StPzXpT2gQn3/fDCTwIZ9nOgaD8buG7da44hFSGX+AaA
   1553 +srgxd3oalJ/Bku2uCId+gmsI9yYszewx++W8H0e2fyrlK6RrXzycYee2v3D
   1554 bRuOulKsO4Bx3Epij1o1VQA0CVaHvCw2+kGpc5Nzh1lm6deMcpoGFAYRxP50
   1555 hn8QVVgxzcl81INd7/9ahlEeFNvlTvVHcTrqT+HoyayfZ4H1ht0JAzzJet/6
   1556 mTzb3uorOu8Ftx9/su0xIhBMXh1B+IESZgqjpS9GtVZMv0qNXx89Pzo8HRwc
   1557 f//s9OlAhmHuD2QQTpZSiZIh1yKS7zYWoT9vIgEdDcX6QZpcyKzoPktBcTSY
   1558 OTAnrDWjABLJ7ilYIxQD55hcxNoUKMxTf2Zz3bsVdqfpcT7CfV4/Y7n1Fbqg
   1559 jfrgndHFdTXBZQxhOd9YrgcGQZoR8wbdYpnYKPFYRctnm60c1iwHAMdgLIsB
   1560 Q6dwAAKw2RY4PtnvPrj/ULy8neV+9yycvNbK1nw2S0FzB5AtXxlCobq0SMeA
   1561 WWBCQid0dtWMilqlcUduRBjEUjvQcMzR5mJLlIJ68xxsZaRh1UwHCIV0dwOm
   1562 pVnO5nHcBXmJgXRyquFAAEEK1Kim7R2pHYI+1R0yR1Vb9Mwn2Y3QBYhev647
   1563 Rshy2xO3GCX74sHpLP/2F7c8MtX3tEXHdpwGod0ubT3njVSGHrzWbctfpYfr
   1564 3DPQmeG024F2g9wOpbkLu4zyGDMBaMXKxCanJerm6KD3xz6qHKCbgdEcBRFG
   1565 7tTmIEWDPnuh1U3tCQdWlklKdhFIjegOl0kKVjPGUUVrHIRtiufRnNq4IGAJ
   1566 6ds9h4665F6VrdF57pBTTWuFBoSeERIygoOEoxitHaWwQwvvhuS0fttEcghl
   1567 E8k1OKzfiuS+0liAvobgnKcAPvnqYE8ofgDQ3FpHRbQJFhURK9CDuttGT5kJ
   1568 rN26Jk7w89tOY8MhRLAzZ6nexQ32UDNStYWamzbsIIVB9kQTG/Wy8kXTufCy
   1569 gUTLGRMrNGPg/ArDXTxcDTSBhh9yxKXyfok9rWclexr7dUgO6i2t2dQ0tP7X
   1570 Npg7HANhN6njiVPjwZHQUhY3jvaxNJRXb6RqZ3ZyE/OcIAQ+piZcaYm7O4XD
   1571 7XF/RLgCP1QY1auxUfo8GTUeFvW8BSNucFz0MqhPuZif6bGZJ/rAlJCuCtK5
   1572 OF5P8VGC3qIItUp2FGbNJI9Y+1Bw+6U0X/Gd6JmV70S7Ta7PzRoo70zjnMQB
   1573 ejne7T6s9ba8Ny4GkOr9WMenWjzOHq7OCvIcxD5oKd0TTG/NMsziuQ/tisVM
   1574 ctZkmQgJjfen6P/OQYf1+TfQYfUzdG5U0pXYA4QZGDpRjjIUujM0WDiKknvu
   1575 fgzp6RA7ofqDsZdEjn0ny46cLjr3EfCJbqNMJsGi41Hq0hnKYgB5qAxBgGSe
   1576 qNRAdAdN5kmIVs80imNoBoe4tS27n7aXjEl6lf7TQHanu72tsjwDsJlgRsxS
   1577 iDAn2uhw5SigiH07kYm8YI9YqDMVdE5TRxmCCQbrDRbLxNBEDBnjSE8epRPe
   1578 u9viRz0ORyld986OfqzRgG90Ruj2DggNfq1Baw/Zk3cawSkr/OkMjI/9UZ7G
   1579 c8zIMA9r+wt40HBYqZFX1WwSj9NDgywF1knPwNIOoOX2Z59sdbe24T+xtbW7
   1580 tSUODk9Oh6KF7Z8fPfpOyFkaTNo90q8prAX2MQflhltXDyo/wxK2XNwiRN/q
   1581 eZ//otstfTTs1MQwnZQ6E5SADQrvWMZMZG+yYjjihtLspb4R7KALKei73S9o
   1582 Z2xLcj+ONTfMHWWgPG8APZwPiin5YiJ9TGlVec+KLCNoFP1GIgI8X2UN5ayi
   1583 mMAiKKwZHFugK1h2JscRuqaQgS3E1/tH+4qAvR/AME5AIBoYxTPul79oGc+X
   1584 n/h2fj7/2jXcMldPBuWT3qSYxiCSaN5s0eOldTPJXFTBlqu1gq20vbW1payd
   1585 r2XSfZKP9QLKaEWDd55aWKJEP3HXDOPjmhsjGIQv4GYtTCTtKXy3VwQ2tBAB
   1586 g24Wy6IMaLTgXCwbwZUnGNltkvDM6BUXwARyXLnFGMyWvipDARjnlzGmyFnO
   1587 h1MibaR/XwQyo5T5MrUbXWWx7PrZmNPuSwc3u7d8ksmAFXXQmIWiF10icQsw
   1588 YNm4BUYO/ScyL3PZQfBgOLj0wnFK5y7l4X+TwFpJSxzqQLdUKahDk19wnmAi
   1589 v49aY5pFQtnRTChqEpNJatLMcPQDYg94cIdsiUeUIqwGGKVpLIEPm4xmjAKY
   1590 3Ochd8OICuoGHt4nEf4ozYp8yYwiRYRcRrnEuZ/hTZO8UGub8V+55czUi1Q5
   1591 +iniCB+hrNJZ0bD3j9P0fD7DQ0oJu6CqZhFwkxxTHy7Q4xAv9OhAQGpQJ5JG
   1592 mb444sl8Kiq5zLA8VnTQXgN6ACQhHLVcYIGUPCedWekJOtdJqw2v24gjJAs7
   1593 F7scMofJebNyncUNZHmCYSpKCy5JjjaIoqnkIIH1sdNlkqXz8QRPxMuXGvsm
   1594 MRETXkAHTtJpixwqbbFHN1nYB6pOy5Z1crbxd2ra4+AwjfAs9hMQKkVrpn7p
   1595 iIbhyl/MAMIaeuuKBtdDCBicKLF7Mh9xBhAJDtCW6W/QIkIen+mVpcoXe9Zr
   1596 eKfpid92nbd87AWKJhYYnClt7pGBdmcQZmVuj4CSzgC9kbqXI/m8TjJJuGeN
   1597 GVgAmqGACGCHlOQN7Fdm+GvxDyr5myQTa05h5I8zfyroohXqmKWs9mdRQZkf
   1598 K0b8ktjX05EWbYfdA0q1Rb32W5glzHzoDOu5VH+ojEMe0dyzwOx78YXYQtUl
   1599 ApLCNHr8TZM9kmmGNzHwSGLyeymnqC0ZZSi8dAfS6dXlAgbZ8ws4iaM5qbm8
   1600 Keoo85SO1xqnCCbAqC13H9E65ffjEzUR6xcFaOhau0BQL8uVn8HetHQAQx1z
   1601 DROlRdvjt73pHEgGhY7yJcAph2XDOApWPr3AS9OsVGFZGqAHVGJsl04f8ocS
   1602 jJ61r+au1un+48PjwZP97wYHTx8dnXBiN4JUcshWyGg6OOnShR3OTzJDgZYi
   1603 1XLZASfgyCch4HlGABx8dcKnXVg/auvX/mgseSxzXMQv71Zr3UPnBXSp5GDB
   1604 gd/w55X3UXfVz0crer4SrW+BueitOXdyd1aA8DZzvvk6qw+sCUVr5CfnIFv9
   1605 JD9D5ch690XDnC1gdygzdvXae5SrwfS7q/L3bhba5nar8dj9aMNhXhmG3nIW
   1606 pC2/9wtNA3xrCGY52TCR7rSJD9rUSbfOtOetCZC3mfPN11l94M4m+prrCfdF
   1607 E5HCj7ubWgXIVULRzUPb3G4tHjcn09bhttrKKM/nmGxCG6mNy/cOUQOMtZ6f
   1608 W/vXqovztruVb7MdS5a1nJ2annhI7ijMzpOV5+LG5qw+WNej7EkaJrtHWiiJ
   1609 j0/2OySnUR0HUxfseEw3Zu8Uy+hVgqrFQhta6gZlAqPO3vSqDFIzxzJGq0R/
   1610 SK7vXCteNpth536ukkF8znQnZc7Xak4u0f0gbfWm1Fg6XpGOOV2M3S9leAbd
   1611 9leor4ENRdfUcfmgTYMZ65/TbEmZFqJuPknQa2PlLiNNC+eO8D41uhHRSwTq
   1612 O8WX/WTB9iT5RpXPchqNJ6TOKV1S3bjVk2AOts5Rixe2jqYOACGjj2giJcZu
   1613 bV1RRrcTqXKH3x083D/6+nAwS/NioNEzIMO7D+YnGvsDQjpYSekcrWZ2yBGq
   1614 eHO6ARp3LTA/RmBWL5ZgBAnLkM060VESz8gvgsmAkOimxGrSKRt4SLURrg1v
   1615 yaLfBuegV8AUdGK5MuAiTCA3XTviFlfbKAmki527obnbdKtDVzWEg2ge157m
   1616 hzs7uy/U1FqTrDbZvbPjNGlK7rX746yTgVZOcSEVSxieYhstiriRG4jW5qw1
   1617 KWLAXYuyhPV7mtYdtNmCdrq2PSMSMYABvLmEHThzBxVtqyMyaw/9c3tC+wC/
   1618 3X/8+PB0cHx4cnj8y8PBt49OH94/3v+2Q8wNLHPl49CgEstABf9V7RWYUoao
   1619 tT7/qjTtCTYXFmPkY7rg1tWWY/PX/mq3VRDUSbc2+oFJu2Z+RrS/Wta2tAkD
   1620 pL8R6mBug+76AbBopnQylWMaf4Rpp/xwABHeitGo68oruqr9pgTxN7y9jJ9K
   1621 DrmjAJpcctVWi7tvvj9AB2Yxz0V6jlY5YpR9qx5b/3vL1/rR2rVW3E0apJGP
   1622 6wVBSlO06yRhK0oWl+B7Ak3bp1iQ5reWCDWy5xLdefLKR+H4pchBY4hDlmEA
   1623 I3oW6F4yggISJfYXX1rnoUlDKtl/I0tHoPjYVfMH7MVtwN14wypB7mZOac1b
   1624 H0e/VCcLAHPOmH5twwNtqoLExifoGP6FdJpQ7NoSh36cST+0PMNfmj1yXGFl
   1625 1PhYBimwgNKzBiodPikdhuSae8alnljE2945/QLZw31J4WF0O/JT10uXknsv
   1626 Jxe7unNr3W0jUsDwKJVusVxv2kfo+Wd4YSuI/WiKBBGZ0NgwSYG8hz1PA6Pv
   1627 uFMRmIh85jNfxbwMV6VLVnAcYOcYbK4xFf3G8dHRK7sEyBLXIkyp4yurXX0d
   1628 pU+THsjOcSzFQTghvyKVwxjafyMhfL4nXI4wbAvy8k1x97nSh8Yrnk7ABwiB
   1629 OUbsCyoRE5t1AtdQAU21TZTZoINYeFs6Rd0rd7APsAZY/Afz9zCwHUo55RZL
   1630 0KeiLVp2gVqqySMgVuDHeWoyK8MIY7d4dXCBtZOYXgjbFO2/xCtxC1KPQ8y6
   1631 VDWKzHpt7+Bqv6BZTvNP3VlY7nG9NTfSQ/Z0LrT1zqwe3xk7bIkB5nbpqCXb
   1632 71xSWjfepq9XjLPMfF/tjKmPA1bvE9Bx+ECu8Vy+D3gqwK1+XY7zOXkW/um4
   1633 i3UmRF8cPTiA/z8/fkSuheviuUXo6L2Mwk6Rnsvky9fta8KzpuG6cTbE5tpx
   1634 lHeauPCK3X1v8GzacONx0B9Im5X3X/KmReHrPkki0f3iOvC0CEmsJPJIvPXt
   1635 a8GzpuGbj7PCXVc7YuvOO9nzzKBXHvn3AU8FuNWvnfMuWnoRHYvT4/Zd+7zz
   1636 j+UQvjY8axquG2dDbG503mF3tfbA2lV9d98bPJs23HicbvOBhwWL7vXOu/pp
   1637 VXXJkgT+zk79nVKfXkYX7w2eCnCrX288jgZF9Mnw6url0sMvrgFPi2u5TAYl
   1638 h6mSyfVX5/IozWzeP5bqjxp39aO3GFAFqTT+2Qf9s4LQeb3xOJ+D0DHJqx3L
   1639 hmCpc2146hLnevCsef1mB7l2ktcxlrvlTnNOX9DMWd4HPBXgVr92zQfDPVpc
   1640 aqL8+TmoATYWNlID7pRqwLJdeW/wbNpw3Th20NOKdQor1gnGeRpHwYLTtFQ4
   1641 EhM38Uqjjmg1WrwtzaCh1WWUyYG6hqjCWNs7n7Y9U1xJgGkoyJmjC3+xtWCc
   1642 ejz8HoiS5oYYrFVz2PGGRmutdLDyqxWhWWXEoE+jVvNROjfT8CIIe+fIyUQ3
   1643 FdDPg35v8vz4yYJRXblH0fMeppcYHqXqW4H2HttXLs7mlOnNBWUvJLqJAL5J
   1644 NFMXLRg5lGrE9yc6nkx8dJ+OcZxu4FPi+RwTnXNxa55o1+It9MzrFKVMxXTV
   1645 aOiDUgFamAzHxBuPWClMXRSZWZ7SlEqa5OpOuMq9Q3/2RRTOyYEVJXlPk8sS
   1646 g8mmGHZO24Yj3gNSRDEZ4GbrmKbZeOVI6ohbeqAuviuz9lUUs6Q6S/hk8mye
   1647 hINQ+iHgTSp60n96Bt4925vBhEh0qBwbds4ng9nZfJa2maanKdNY0YYkdROv
   1648 VKesYggBbFqC+cj/ePL0yFh07WoU6snhMYa+TwcHT49Oj/cPTm3trDGs5zj/
   1649 anG9ZVZSedTeIbSNUSpXPayGqap4VojGSMDp0/tPd1W4v8uqFqdq0iVuevBl
   1650 tTj0GAvtRVSX5wAo/UTGqooDUKVOrxgtSo/+pTQBDIw56hiJrj9u+8M90JRz
   1651 PZ7yz+65sxjE9V4a4iPKfN1Wq+Hkdime+Nn5/QhrjiMnqseXdNinDPJ0qvBg
   1652 zNWGx6P7JRxOq8Q4MUt2cP/w2dOTR6cdJbRa1s5VgpGellr4EKlDxSTN6tSx
   1653 f1WNOJmOpqU5cfbDytlze1kBiI+EE3ZUuphp3vQSHtv0Vl0D1W4wQUfnWNmZ
   1654 Dh2FyTbFrrVxhBxHt3qJxIxBOLXy17Xt6ah5rOwix+gyOWJ1E0ydZ3ME5NUs
   1655 xiiPQ2uahS+xfuss3ERy9Uw9G2Ki5j3hxnOojAHtobBevbTYqMM1a1z1NQ+g
   1656 ZERLCQVLP/g5cc66YWdnQbiSziyrZ8m88uFm0m9ZUBkvs9ubFCXLUijqx29l
   1657 HoUa1UqjoOh8w5QlXSw/hO+Y2azlMYY2HSZTPl3GZfSa35qPNEo7K1yvuUjH
   1658 xi2JvpsL+VfSL3RbdetHJV+YC2Jq/zHcnoVeDlQezmO8s2zlx5Nyi/TrlWhF
   1659 oXzZqh5Ak7QHB/DBo+Mn7qZXttxsp41HlSnTvH+u2lfd86bdfbWexzXk5rib
   1660 o5NznN1vzq9yIq01doK6daP3wObMb6k/v4f9MFy/aTtWSvR3uRuNR8/1WpWK
   1661 5hKx8Wz/+yeH8O/Tb95UcNi5Q40uiVLpviYM11KkrcQa3AUsEka/YH0F7SnA
   1662 mlLqGhp+LYgbqvQXNjNryS+Ck18iKn4PhrBMTMZG6KRmeOp+ps7AAWWXsmj5
   1663 wq4zpBlp5qOSDrZq9WJZi7+PozoPm8lvqG72m3Exn42utPszNswLqqtFq7yI
   1664 fErpGGFmNn7PK07HUcBpzlR9U5JBH8oAK30W5lKcurCmEnt4MKxyfCnjGK13
   1665 vq9M9vQH5qSbdG6uANAyqTB4d9bPinjRxhopeBEWM6B73j4h2UEBIskH9M4K
   1666 uotqFqL2jwtVcEoQ5zepa/llehHf5xv5wXnPzoZSGXGAoUBy7jeMnEkwptQO
   1667 qj9xB8s51Fbkuq4pvJlyPTIPRlAQzBPYl3N/FMVRgfngj4BYsBJGUc4OeyDj
   1668 M1odJ+AolMEgTsZNx4uYXunDCpWUoIrLBoCL00s7/zw6Y9cMZmChCwbUyI75
   1669 EFBeZPOAXTiue4dqSPmLvtZuWvRtKV0CYySLSyRafZm0PCH4OTCdv/OOEoJ0
   1670 LLDWbn0qkFrNQMl7fmhkwLKf5c5KxJKlm7xj73A97rZuHHNl0T4uDXHA9wXP
   1671 pg03HqcxRKyW+0ZBYtGypM714VnT8M3HWeqfb8i62iAJTKGIGB+X2m2K7b0H
   1672 eCrArX69eXhY0E0boArrdNqEcR2IuGIAmS12mBi9/ddfWy00TH6r661uzesb
   1673 Dr7eQHRY4f3dBIf/GrFhDB26yrXeSYToby1dZKfcoTQ5i3Qu+N9SughHdXVt
   1674 D7CaeEHKn8hwXB/b9mHdPFnIvS7gGGr0URsqMEfOhWlU0PWAjUdes4CbzCXd
   1675 sdQG1Lz/HnJJr3mT1q5ajbGOv/z7T//x+/+h8r7LGt1NKtabBpdq1bJXzdss
   1676 yOt+bguE0v2pO6bQaxRLT/m02a3l5ty7d9RMkC/Cm59fbni3re6z1FIV4+4M
   1677 i7IvzfHJZzHdLwEradHkXjVOg+PDB8+P7mvXatWxY1/nfAViG/5n5q74OhUg
   1678 K4IidccHRTSutW81kehXWa/tZ3dtliWbUSLNGP4jadWmUiYrfzBR2084LRl7
   1679 pCv9wsQfS3Tp2pAVu2nlDqMdtNlW3cQ+beYXcqJPVqUnHPqLvaaxzZ1B55TQ
   1680 J41S8giTs9C4iMsweSanYGz35zN0ZwjtUQ7d9t7UzxjTjGL0ACToTyjWoo48
   1681 Y5qP6K1st0sCwFgwXb/nD6Rp9sZ5BT4lQfxqy2um7roD9/rUvUydsPlSjWe8
   1682 p1UvCVHU/KQOvQihNtP1l8Fzo2RgLK+0EvQ1R7QQnOgH8ti2x76oPbp4BnjU
   1683 /cyNwI3FTpOIXnFDc2MIDUfGmJBau2Yl+HWsMpnH+S6edp01XnK06oppz1is
   1684 v1xtfLXUnZy15HRrvriYDIHHXS6/Abj65p8HCDF+Rf1FozTGmrQwTG0AMaS/
   1685 GoqQ9ayyjly2LZN+zmUbrftzhh2HKX3QcdfztnurkKGczFw0gyrw+U6JXgTz
   1686 g1w5NMM5Z0YZZ3vN8dzx0H2sq6s6cUx9m1FdZfR2NoHLtxzdmvpKXyn62F+3
   1687 vTs92E3YJIaN2JwSQFE15srlMa0KhcYDi9XWMHNNbYAqekl772zxB6r0cUO1
   1688 tnxpubb11dkABs4PY0zr26yGUnoMeCXPTvrBxJAn+mxDcmsbOuWDrMuYqRKX
   1689 cJyonjPsNZdTCUtywwnVlttTDU0hkaGH7nxf4JeU8HNJ6hYzTshfnzG8Y1ip
   1690 i6cOnKpersrfqe4RVWzl/DciAv4CMDRADRLkGX9h2wKDogpUTRPopnRHK9rA
   1691 h/RV3lO6rGq+SyyTnAr/Ud6ikzvI57vlTFdJbGzzndlMXVs1yYJOjVTaeF/X
   1692 bjQCG3RNovIim5OCRJECrGOD4R88dRN/BvKYVjWzrlcr6u1Q+gC+VOSqvw3i
   1693 4FR9/8epY6mv8uvSKdXaJ7qLqnuySbETPcqt0Xl+q+POAAPBI/wQLWdT6Lon
   1694 3AGfrO+xrAyKqYFiqm2uKm7SUNlkVVmTpSUs7PoVQn0Wl9OQqoOXPcphdQWj
   1695 8mt6wKDmRRf2thtMUqxWbGjX0DzXdMZMoinmZ4rhn/+4d4fKx0qUf4HUVGiR
   1696 tofHo+kQLqmARPdYqPi+KdJC1TBNXQEYggRYCxhL689/7G63+3/+o5EKmEbb
   1697 wc+S0q38hD5BGGDeoB9zVWHUWv0rIS98+mSvqfk8T0xYCD+arQhY1a7murk4
   1698 x2VKR0TJrycy1iXmbSalDJnpNNK5tgAhrYBLEuvvLZg9NgwyR+lzLC+objhX
   1699 acclmhpSQ3LpcIkmGxtl4rEKgs24PDfFtfRI+Kqle7c3BKj3M6p2qeNUgOFr
   1700 /dx0dbW1Zc6EFXQicKeKUDaZ+G3mrD7YoNOSntX5RR/XIKqPl5QgZEbUlAyp
   1701 XJMroFWSRDHhpvKFP4PihXpXNhxPBQDG/nTql7m5ik8Afdx4KcNrwtcAca2n
   1702 ujEkWn/6Q/UimHt96B0UM1xL/8ZZq7+pXvLQN7/zs3bO6oO1C1za055W9JlJ
   1703 d+snbsVxQ2mDIk65/Wsy4mdxdK5zXugKil6VUJkxtKHvE5IG2JadDNq7/6z1
   1704 WfasPljXo+z5FhGKfh+VyWr5SPyiJh6nAd6M8xoUSuH00zIIjHM/4VM0KNLB
   1705 ORhD/qDsmuNI2pZybdqV45Uj4Kh6AIbNuPJmwMeKhUDDUFjfPyWh4Voh5Hwp
   1706 v9ve4fga/FsFDZoaR4zSzUqTgBu5cFNZSHkxQLei1TSHtm5D1gkHSpE0DQdc
   1707 XDPnAazj3Igd3KSyzdpYk6NZ2eVcS/2hUpOzad+1Dai6dfkiPe3urU5FGTHW
   1708 Xkecf6gz9c+Vc/HPf0Tv4nKCqE6km3WVKd/FTwvfsqt+wgBshSYfsh1a82WK
   1709 pi3es8ml1QANp/PaFpnuY396uaFjx1jCPESr9OW4Rqd+5tKWbYDyE/SxNvoK
   1710 dAfbxq3Q396SQoqGXkTpYyaw2cunYhvkW6tXMbxGgUOLmi1QHOqrlXI0jgQV
   1711 06mySMUnmxeWK4pti4YrIuvrr25e9dRgsNNEzvMRyrQlRTPpjseTw8cmt9zC
   1712 klq+LkLYcNtDYUWHuZy9ak61t04kJV9bV6rMjpOK2uv1rDCJfXewIdpArOnw
   1713 IXCtJIyBMSOTWRvKXKvcu9FMrsPoxg1NWNi6rbPmqs7a+yLWZRHrpgif4TLS
   1714 SURZzhTiDcQ1BV43opL3W/6VqOeDd3TerXjpB3gjjg9wwz0bfclGlQqvy4gG
   1715 Nl4Tw8vcfjfEGP+qzOv9c46lN7KqVyY0BhqyDCzNhEzgAf0Xpni9caCChVZf
   1716 D5SwymhIs2f4NRnc8z/9AboQSWB5StZSmmljs4q4P9lk8ZMt6jHoMFDfnW65
   1717 Cs2yg9sR9aPPJcL5lppmszV0OYYoYqluDtlaQA6gdsSZH+MX9Qyca+8vLSUT
   1718 FUD40x+Wlb5eejXL4f9KO82zoB9Ho77uNPBnERWiJ8u8F2C4HQUEWxZnURLl
   1719 E+BCa3tb5j0OMpMZRo8H2uG+Ntpd93GU2u+Bug5fumeYab4xSoFOr3uvqkId
   1720 IGYROgyeAmqcWswV5kic/Vz8Yg9m3aWohuvGwKLEtna8fOts6c2jbCDEl3oc
   1721 bMl9DQ6xCe0v5x+McpL5GJwv08HAIFyHuP+/rJCBZsZ/n+bFBzcsojeS0Vo1
   1722 LNWEPeuvD6pn3JIAZjf4g9aDN2KwFRZpHeFBer6aQb5Jvfaf/rJJyfafanZu
   1723 Rexep3D7T9WL3BqGZeXbf7LyRqsV3GuF1X9y045ui8eYjvDyNiUggJSgrIJq
   1724 a5VcJEOTxKApuZrHYN0HxEyBkSzTJEAANidJbJbGoTJ+ahkUHY8+emM+D6Nz
   1725 gMQkwi8HLoRMQvoC+M0FLNcHGrld5Qjoy3DOTThz8jb8eVtXL9ijGjFLr7vd
   1726 5JzVB+t6LO+p/Oj2xSW+taTXww2WRULsn9a6aoNvD21zuxuLgXCGNB1BpfTF
   1727 rG38nGMguH0tYtWkzL/z6Mda+nQ/B+gH/zyP8miT2OBbzVl9sKaD1fOa0Y9r
   1728 XdCocoVllQjIHH/46OT06fH3g+PDf3p+eHLaEepD9ahtbOSOe5P7AA3UvrH+
   1729 rbjuUu3bGOylrdlouGMjysfWVIyKDQ5q+jWN3/YkGLKr+10TJ41UW+7Zepi+
   1730 xAUacLybsP9hQDNlg0a1zqm3kT9spVkA9GVTWn0FG0Un/n4Nhv906dneCDzP
   1731 9XOhMiZluIQA341dcNOWwc3YBua7S9op0PjZpVOdMwy6PH91Cb/UtHNpf85d
   1732 f8adREwhrwrPOy2vSeSIYtXVLZ2R98AkmU4p4xiAoORlqtoCdoKUWbdIu/iv
   1733 fecCujxK+FvzHWFV5dCf7tYlPin7mZLuA5xKl8jFIZVd4A5KGNkPArqDd5BJ
   1734 9gDRSrs+P36tPjc1h3Xozzxxg9mc7mtYaMNmcVxrFsdOM3Eig3kWFQtxgNmm
   1735 oa4V43m/+kGcfnVf/OoFtnq0f7Rfa3EEsgrARq0LC7tgu1OU7L+UuA10sSDK
   1736 BaVxh9EV14cNMdf8MgUxq/JascMFd+AcWXiAdhgnCD/T5p/76Uz+ctOC0g/K
   1737 b3cCtx+nbMNl6Xw8ceuyWHVwdOncNI5TuiNBF5o4s/Zb/cVjhFLdcWF2/ju+
   1738 A6H++rGaSDxUH5obalNVs0hKu9/p4U6YCy/6+15lhjPulbnp4M7I908iv97g
   1739 x2H9wkkPb3/wPRKrp1VfqRyc7h5ycTXG/aSErHqnpOfd7ZkrQnQPJL3sUrTO
   1740 AgavbgDarOtB/Or3Dur+ZVi35nvexzi83sylHVdcg7DRYa473OvxUZL0VTV1
   1741 jIa0WjgPRoLnZtOsw4b9P+nBCVF7wAcJb26YcVbv3++HHeXZQCJTD/91aM9F
   1742 5xYn+hSXr6thNc3VUeWd8EtuWKpq9dT/2jT1f69MDbwAp/6spxkxDlcdCTo5
   1743 3hn7hg8egBIZFbrXzByn2N5aOce/VOYwV5BogurmVoQFjk/XWhxeQmcccBWm
   1744 wZxwOaHPBiLndzgGgvP10XPFb0gESCz7W/lW72WGpQLwvp046Hn7gPFRlPgg
   1745 a6jgOX1dj7gbuYgm8srH4l34ebYk5RF6LMoQxAMsQ7XNejaJSziM+lrId999
   1746 Zz0jb7bzSOtxzkNbIXPf/dgw7o/1cX9sGvfHpnFJdJN0+bakg5e3i2DbfCH4
   1747 9Rt8AtsG0/qGaOWJ+oSnDcpbfTUZR2HjgqINv6s/+lE9cpX43zU+/dHqXtlR
   1748 RcH1R/Yem0bmidKmygnNAz1Xqer/rvbkR9Op3sp+ptuxJo2/sd7p4njzr/Pq
   1749 T7haGIrGNaThox/rO7nSh65xVsKncVaBePk3OZFQy+9yOiUK8ZUpU+heiFWv
   1750 1KVYy6uNL5Rne4n2RidjnQanGyktrkF5K1uQAmcpz0vPYalMW60b12S3tFjU
   1751 Dmp0B3z5NE7H+Nd+oOUuwpV7L3eT+XQELDPcu0XB9FuvHc2RNMDLNDsH5Re/
   1752 MjCbpZnyo9OdWs2AZTYF+fxAonYZiycY0C4yvNDpHYJSX57oY+AEfgZSsPXV
   1753 k68etEkYlQX4fo03wEBLxfMo8RdKjQFl8f8BaKB3bXTAAAA=
   1754 
   1755 -->
   1756 
   1757 </rfc>