lsd0009

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

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


      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="08"/>
     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-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 
    326 {::comment}
    327 see GNUNET_CRYPTO_eddsa_ecdh
    328 {:/}
    329 ]]></artwork>
    330           <artwork><![CDATA[
    331 ECDH-GetPub(priv) -> pub
    332 
    333 Input:
    334     priv    private X25519 key
    335 
    336 Output:
    337     pub     public X25519 key
    338 ]]></artwork>
    339           <t><tt>pub</tt> is calculated according to Section 6.1 of <xref target="RFC7748"/>:</t>
    340           <artwork><![CDATA[
    341 pub = X25519(priv, 9)
    342 ]]></artwork>
    343         </section>
    344       </section>
    345       <section anchor="blind-signatures">
    346         <name>Blind Signatures</name>
    347         <section anchor="rsa-fdh">
    348           <name>RSA-FDH</name>
    349           <section anchor="supporting-functions">
    350             <name>Supporting Functions</name>
    351             <artwork><![CDATA[
    352 RSA-FDH(msg, pubkey) -> fdh
    353 
    354 Inputs:
    355     msg     message
    356     pubkey  RSA public key consisting of modulus N and public exponent e
    357 
    358 Output:
    359     fdh     full-domain hash of msg over pubkey.N
    360 ]]></artwork>
    361             <t><tt>fdh</tt> is calculated based on HKDF-Mod from <xref target="hkdf-mod"/> as follows:</t>
    362             <artwork><![CDATA[
    363 info = "RSA-FDA FTpsW!"
    364 salt = uint16(bytes(pubkey.N)) | uint16(bytes(pubkey.e))
    365      | pubkey.N | pubkey.e
    366 fdh = HKDF-Mod(pubkey.N, salt, msg, info)
    367 ]]></artwork>
    368             <t>The resulting <tt>fdh</tt> can be used to test against a malicious RSA pubkey
    369 by verifying that the greatest common denominator (gcd) of <tt>fdh</tt> and <tt>pubkey.N</tt> is 1.</t>
    370             <artwork><![CDATA[
    371 RSA-FDH-Derive(bks, pubkey) -> out
    372 
    373 Inputs:
    374     bks     blinding key secret of length L = 32 octets
    375     pubkey  RSA public key consisting of modulus N and public exponent e
    376 
    377 Output:
    378     out     full-domain hash of bks over pubkey.N
    379 ]]></artwork>
    380             <t><tt>out</tt> is calculated based on HKDF-Mod from <xref target="hkdf-mod"/> as follows:</t>
    381             <artwork><![CDATA[
    382 info = "Blinding KDF"
    383 salt = "Blinding KDF extractor HMAC key"
    384 fdh = HKDF-Mod(pubkey.N, salt, bks, info)
    385 ]]></artwork>
    386           </section>
    387           <section anchor="blinding">
    388             <name>Blinding</name>
    389             <artwork><![CDATA[
    390 RSA-FDH-Blind(msg, bks, pubkey) -> out
    391 
    392 Inputs:
    393     msg     message
    394     bks     blinding key secret of length L = 32 octets
    395     pubkey  RSA public key consisting of modulus N and public exponent e
    396 
    397 Output:
    398     out     message blinded for pubkey
    399 ]]></artwork>
    400             <t><tt>out</tt> is calculated based on RSA-FDH from <xref target="rsa-fdh"/> as follows:</t>
    401             <artwork><![CDATA[
    402 data = RSA-FDH(msg, pubkey)
    403 r = RSA-FDH-Derive(bks, pubkey)
    404 r_e = r ** pubkey.e (mod pubkey.N)
    405 out = r_e * data (mod pubkey.N)
    406 ]]></artwork>
    407           </section>
    408           <section anchor="signing-1">
    409             <name>Signing</name>
    410             <artwork><![CDATA[
    411 RSA-FDH-Sign(data, privkey) -> sig
    412 
    413 Inputs:
    414     data    data to be signed, an integer smaller than privkey.N
    415     privkey RSA private key consisting of modulus N and private exponent d
    416 
    417 Output:
    418     sig     signature on data by privkey
    419 ]]></artwork>
    420             <t><tt>sig</tt> is calculated as follows:</t>
    421             <artwork><![CDATA[
    422 sig = data ** privkey.d (mod privkey.N)
    423 ]]></artwork>
    424           </section>
    425           <section anchor="unblinding">
    426             <name>Unblinding</name>
    427             <artwork><![CDATA[
    428 RSA-FDH-Unblind(sig, bks, pubkey) -> out
    429 
    430 Inputs:
    431     sig     blind signature
    432     bks     blinding key secret of length L = 32 octets
    433     pubkey  RSA public key consisting of modulus N and public exponent e
    434 
    435 Output:
    436     out     unblinded signature
    437 ]]></artwork>
    438             <t><tt>out</tt> is calculated as follows:</t>
    439             <artwork><![CDATA[
    440 r = RSA-FDH-Derive(bks, pubkey)
    441 r_inv = inverse of r (mod pubkey.N)
    442 out = sig * r_inv (mod pubkey.N)
    443 ]]></artwork>
    444           </section>
    445           <section anchor="verifying-1">
    446             <name>Verifying</name>
    447             <artwork><![CDATA[
    448 RSA-FDH-Verify(msg, sig, pubkey) -> out
    449 
    450 Inputs:
    451     msg     message
    452     sig     signature of pubkey over msg
    453     pubkey  RSA public key consisting of modulus N and public exponent e
    454 
    455 Output:
    456     out     true, if sig is a valid signature
    457 ]]></artwork>
    458             <t><tt>out</tt> is calculated based on RSA-FDH from <xref target="rsa-fdh"/> as follows:</t>
    459             <artwork><![CDATA[
    460 data = RSA-FDH(msg, pubkey)
    461 exp = sig ** pubkey.e (mod pubkey.N)
    462 out = (data == exp)
    463 ]]></artwork>
    464           </section>
    465         </section>
    466         <section anchor="clause-schnorr">
    467           <name>Clause-Schnorr</name>
    468         </section>
    469       </section>
    470     </section>
    471     <section anchor="datatypes-and-notation">
    472       <name>Datatypes and Notation</name>
    473       <section anchor="amounts">
    474         <name>Amounts</name>
    475         <t>Amounts are represented in Taler as positive fixed-point values
    476 consisting of <tt>value</tt> as the non-negative integer part of the base currency,
    477 the <tt>fraction</tt> given in units of one hundred millionth (1e-8) of the base currency,
    478 and <tt>currency</tt> as the 3-11 ASCII characters identifying the currency.</t>
    479         <t>Whenever used in the protocol, the binary representation of an <tt>amount</tt> is
    480 <tt>uint64(amount.value) | uint32(amount.fraction) | padZero(12, amount.currency)</tt>.</t>
    481       </section>
    482       <section anchor="timestamps">
    483         <name>Timestamps</name>
    484         <t>Absolute timestamps are represented as <tt>uint64(x)</tt> where <tt>x</tt> corresponds to
    485 the microseconds since <tt>1970-01-01 00:00 CEST</tt> (the UNIX epoch).
    486 The special value <tt>0xFFFFFFFFFFFFFFFF</tt> represents "never".
    487 <!--
    488 // todo: check if needed and correct
    489 Relative timestamps are represented as `uint64(x)` where `x` is given in microseconds.
    490 The special value `0xFFFFFFFFFFFFFFFF` represents "forever".
    491 -->
    492         </t>
    493       </section>
    494       <section anchor="signatures">
    495         <name>Signatures</name>
    496         <t>All messages to be signed in Taler start with a header containing their size and
    497 a fixed signing context (purpose) as registered by GANA in the
    498 <eref target="https://gana.gnunet.org/gnunet-signatures/gnunet_signatures.html">GNUnet Signature Purposes</eref>
    499 registry. Taler-related purposes start at 1000.</t>
    500         <artwork><![CDATA[
    501 Gen-Msg(purpose, msg) -> out
    502 
    503 Inputs:
    504     purpose signature purpose as registered at GANA
    505     msg     message content (excl. header) to be signed
    506 
    507 Output:
    508     out     complete message (incl. header) to be signed
    509 ]]></artwork>
    510         <t><tt>out</tt> is formed as follows:</t>
    511         <artwork><![CDATA[
    512 out = uint32(len(msg)) | uint32(purpose) | msg
    513 ]]></artwork>
    514       </section>
    515       <section anchor="helper-functions">
    516         <name>Helper Functions</name>
    517         <t>There are a certain number of single-argument functions which are often needed,
    518 and therefore omit the parentheses of the typical function syntax:</t>
    519         <ul spacing="normal">
    520           <li>
    521             <t><tt>Knows data</tt> specifies <tt>data</tt> that is known a priori at the start of the protocol operation</t>
    522           </li>
    523           <li>
    524             <t><tt>Check cond</tt> verifies that the boolean condition or variable <tt>cond</tt> is true,
    525 or aborts the protocol operation otherwise</t>
    526           </li>
    527           <li>
    528             <t><tt>Persist data</tt> persists the given <tt>data</tt> to the local database</t>
    529           </li>
    530           <li>
    531             <t><tt>data = Lookup by key</tt> retrieves previously persisted <tt>data</tt> by the given <tt>key</tt></t>
    532           </li>
    533           <li>
    534             <t><tt>Sum ⟨dataᵢ⟩</tt> is valid for numerical objects <tt>dataᵢ</tt> including amounts (cf. <xref target="amounts"/>),
    535 and denotes the numerical sum of these objects</t>
    536           </li>
    537         </ul>
    538         <t>Some more functions that are commonly used throughout <xref target="protocol"/>:</t>
    539         <artwork><![CDATA[
    540 Hash-Denom(denom) =
    541   SHA-512(uint32(0) | uint32(1) | denom.pub)
    542 
    543 Hash-Planchet(planchet, denom) =
    544   SHA-512( SHA-512( denom.pub ) | uint32(0x1) | planchet )
    545 
    546 Check-Subtract(value, subtrahend) =
    547   Check value >= subtrahend
    548   Persist value -= subtrahend
    549 ]]></artwork>
    550       </section>
    551     </section>
    552     <section anchor="protocol">
    553       <name>The Taler Crypto Protocol</name>
    554       <t>// todo: briefly introduce the three components wallet, exchange, merchant; maybe with ASCII diagram version</t>
    555       <t>// todo: capitalize wallet, exchange, merchant?</t>
    556       <section anchor="withdrawal">
    557         <name>Withdrawal</name>
    558         <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,
    559 attributing value to the coins according to <tt>n</tt> chosen denominations <tt>⟨denomᵢ⟩</tt>.
    560 The total value and withdrawal fee (defined by the exchange per denomination)
    561 must be smaller or equal to the amount stored in the single reserve used for withdrawal.</t>
    562         <t>// todo: document TALER_MAX_COINS = 64 per operation (due to CS-encoding)</t>
    563         <t>// todo: extend with extra roundtrip for CBS</t>
    564         <artwork><![CDATA[
    565             wallet                                  exchange
    566 Knows ⟨denomᵢ⟩                          Knows ⟨denomᵢ.priv⟩
    567                |                                        |
    568 +-----------------------------+                         |
    569 | (W1) reserve key generation |                         |
    570 +-----------------------------+                         |
    571                |                                        |
    572                |----------- (bank transfer) ----------->|
    573                | (subject: reserve.pub, amount: value)  |
    574                |                                        |
    575                |                      +------------------------------+
    576                |                      | Persist (reserve.pub, value) |
    577                |                      +------------------------------+
    578                |                                        |
    579 +-----------------------------------+                   |
    580 | (W2) coin generation and blinding |                   |
    581 +-----------------------------------+                   |
    582                |                                        |
    583                |-------------- /withdraw -------------->|
    584                |    (reserve.pub, planchets, sig)       |
    585                |                                        |
    586                |                      +--------------------------------+
    587                |                      | (E1) coin issuance and signing |
    588                |                      +--------------------------------+
    589                |                                        |
    590                |<---------- (⟨blind_sigᵢ⟩) -------------|
    591                |                                        |
    592 +----------------------+                                |
    593 | (W3) coin unblinding |                                |
    594 +----------------------+                                |
    595                |                                        |
    596 ]]></artwork>
    597         <t>where (for RSA, without age-restriction)</t>
    598         <artwork><![CDATA[
    599 (W1) reserve key generation (wallet)
    600 
    601 reserve = Ed25519-Keygen()
    602 Persist (reserve, value)
    603 ]]></artwork>
    604         <t>The wallet derives coins and blinding secrets using a HKDF from a single seed per withdrawal operation,
    605 together with an integer index.
    606 This is strictly speaking an implementation detail since the seed is never revealed to any other party,
    607 and might be chosen to be implemented differently.</t>
    608         <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>
    609         <artwork><![CDATA[
    610 (W2) coin generation and blinding (wallet)
    611 
    612 batch_seed = random(256)
    613 Persist batch_seed
    614 for i in 0..n:
    615   coin_seedᵢ = HKDF(uint32(i), batch_seed, "taler-withdrawal-coin-derivation", 64)
    616   blind_secretᵢ = coin_seedᵢ[32:]
    617   coinᵢ.priv = coin_seedᵢ[:32]
    618   coinᵢ.pub = Ed25519-GetPub(coinᵢ.priv)
    619   h_denomᵢ = Hash-Denom(denomᵢ)
    620   planchetᵢ = RSA-FDH-Blind(SHA-512(coinᵢ.pub), blind_secretᵢ, denomᵢ.pub)
    621   h_planchetᵢ = Hash-Planchet(planchetᵢ, denomᵢ)
    622 planchets = (⟨h_denomᵢ⟩, ⟨planchetᵢ⟩)
    623 msg = Gen-Msg(WALLET_RESERVE_WITHDRAW,
    624     ( Sum ⟨denomᵢ.value⟩ | Sum ⟨denomᵢ.fee_withdraw⟩
    625     | SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
    626 sig = Ed25519-Sign(reserve.priv, msg)
    627 ]]></artwork>
    628         <artwork><![CDATA[
    629 (E1) coin issuance and signing (exchange)
    630 
    631 (⟨h_denomᵢ⟩, ⟨planchetᵢ⟩) = planchets
    632 for i in 0..n:
    633   denomᵢ = Lookup by h_denomᵢ
    634   Check denomᵢ known and not withdraw-expired
    635   h_planchetᵢ = Hash-Planchet(planchetᵢ, denomᵢ)
    636 msg = Gen-Msg(WALLET_RESERVE_WITHDRAW,
    637     ( Sum ⟨denomᵢ.value⟩ | Sum ⟨denomᵢ.fee_withdraw⟩
    638     | SHA-512( ⟨h_planchetᵢ⟩ ) | uint256(0x0) | uint32(0x0) | uint32(0x0) ))
    639 Check Ed25519-Verify(reserve.pub, msg, sig)
    640 Check reserve KYC status ok or not needed
    641 total = Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
    642 Check-Subtract(reserve.balance, total)
    643 for i in 0..n:
    644   blind_sigᵢ = RSA-FDH-Sign(planchetᵢ, denomᵢ.priv)
    645 Persist withdrawal // todo: what exactly? should be checked first for replay?
    646 ]]></artwork>
    647         <artwork><![CDATA[
    648 (W3) coin unblinding (wallet)
    649 
    650 for i in 0..n:
    651   coinᵢ.sig = RSA-FDH-Unblind(blind_sigᵢ, blind_secretᵢ, denomᵢ.pub)
    652   Check RSA-FDH-Verify(SHA-512(coinᵢ.pub), coinᵢ.sig, denomᵢ.pub)
    653   coinᵢ.h_denom = h_denomᵢ
    654   coinᵢ.blind_secret = blind_secretᵢ  // todo: why save blind_secret, if batch_seed already persisted?
    655 Persist ⟨coinᵢ⟩
    656 ]]></artwork>
    657       </section>
    658       <section anchor="payment">
    659         <name>Payment</name>
    660         <t>The wallet obtains <tt>contract</tt> information for an <tt>order</tt> from the merchant
    661 after claiming it with a <tt>nonce</tt>.
    662 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>,
    663 where the sum of all contributions (<tt>contributionᵢ &lt;= denomᵢ.value</tt>) must match the <tt>contract.price</tt> plus potential deposit fees.
    664 The payment is complete as soon as the merchant successfully redeems the deposit authorizations at the exchange (cf. <xref target="deposit"/>).</t>
    665         <artwork><![CDATA[
    666             wallet                                  merchant
    667 Knows ⟨coinᵢ⟩                           Knows merchant.priv
    668                                         Knows exchange, payto
    669                |                                        |
    670                |                      +-----------------------+
    671                |                      | (M1) order generation |
    672                |                      +-----------------------+
    673                |                                        |
    674                |<------- (QR-Code / NFC / URI) ---------|
    675                |          (order.{id,token?})           |
    676                |                                        |
    677 +-----------------------+                               |
    678 | (W1) nonce generation |                               |
    679 +-----------------------+                               |
    680                |                                        |
    681                |------- /orders/{order.id}/claim ------>|
    682                |       (nonce.pub, order.token?)        |
    683                |                                        |
    684                |                      +--------------------------+
    685                |                      | (M2) contract generation |
    686                |                      +--------------------------+
    687                |                                        |
    688                |<---- (contract, merchant.pub, sig) ----|
    689                |                                        |
    690 +--------------------------+                            |
    691 | (W2) payment preparation |                            |
    692 +--------------------------+                            |
    693                |                                        |
    694                |------- /orders/{order.id}/pay -------->|
    695                |             (⟨depositᵢ⟩)               |
    696                |                                        |
    697                |                      +--------------------+
    698                |                      | (M3) deposit check |
    699                |                      +--------------------+
    700                |                                        |
    701                |<--------------- (sig) -----------------|
    702                |                                        |
    703 +---------------------------+                           |
    704 | (W3) payment verification |                           |
    705 +---------------------------+                           |
    706                |                                        |
    707 ]]></artwork>
    708         <t>where (without age restriction, policy and wallet data hash)</t>
    709         <artwork><![CDATA[
    710 (M1) order generation (merchant)
    711 
    712 wire_salt = random(128)
    713 determine id, price, info, token?
    714 Persist order = (id, price, info, token?, wire_salt)
    715 ]]></artwork>
    716         <artwork><![CDATA[
    717 (W1) nonce generation (wallet)
    718 
    719 nonce = Ed25519-Keygen()
    720 Persist nonce.priv
    721 ]]></artwork>
    722         <t>Note that the private key of <tt>nonce</tt> is currently not used anywhere in the protocol.
    723 However, it could be used in the future to prove ownership of an order transaction,
    724 enabling use-cases such as "unclaiming" or transferring an order to another person,
    725 or proving the payment without resorting to the individual coins.</t>
    726         <artwork><![CDATA[
    727 (M2) contract generation (merchant)
    728 
    729 Check order.token? == token?
    730 h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
    731 determine timestamp, refund_deadline, wire_deadline
    732 contract = (order.{id,price,info,token?}, exchange, h_wire, timestamp, refund_deadline, wire_deadline)
    733 contract.nonce = nonce.pub
    734 Persist contract
    735 h_contract = SHA-512(canonicalJSON(contract))
    736 msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
    737 sig = Ed25519-Sign(merchant.priv, msg)
    738 ]]></artwork>
    739         <artwork><![CDATA[
    740 (W2) payment preparation (wallet)
    741 
    742 h_contract = SHA-512(canonicalJSON(contract))
    743 msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
    744 Check Ed25519-Verify(merchant.pub, msg, sig)
    745 Check contract.nonce == nonce
    746 // TODO: double-check extra hash check?
    747 // todo: maybe get rid of CoinSelection altogether by claiming we already know coinᵢ and contributionᵢ
    748 ⟨selectionᵢ⟩ = CoinSelection(contract.{exchange,price}) TODO: include MarkDirty here
    749 for i in 0..n:
    750   (coinᵢ, denomᵢ, contributionᵢ) = selectionᵢ
    751   msgᵢ = Gen-Msg(WALLET_COIN_DEPOSIT,
    752       ( h_contract | uint256(0x0)
    753       | uint512(0x0) | contract.h_wire | coinᵢ.h_denom
    754       | contract.timestamp | contract.refund_deadline
    755       | contributionᵢ + denomᵢ.fee_deposit
    756       | denomᵢ.fee_deposit | merchant.pub | uint512(0x0) ))
    757   sigᵢ = Ed25519-Sign(coinᵢ.priv, msgᵢ)
    758   depositᵢ = (coinᵢ.{pub,sig,h_denom}, contributionᵢ, sigᵢ)
    759 Persist (contract, ⟨sigᵢ⟩, ⟨depositᵢ⟩)
    760 ]]></artwork>
    761         <t>// TODO: explain CoinSelection</t>
    762         <t>// TODO: maybe introduce symbol for pub/priv</t>
    763         <artwork><![CDATA[
    764 (M3) deposit check (merchant)
    765 
    766 Check Sum ⟨depositᵢ.contribution⟩ == contract.price
    767 Check Deposit(⟨depositᵢ⟩)
    768 msg = Gen-Msg(MERCHANT_PAYMENT_OK, h_contract)
    769 sig = Ed25519-Sign(merchant.priv, msg)
    770 ]]></artwork>
    771         <artwork><![CDATA[
    772 (W3) payment verification (wallet)
    773 
    774 msg = Gen-Msg(MERCHANT_PAYMENT_OK, h_contract)
    775 Check Ed25519-Verify(merchant.pub, msg, sig)
    776 ]]></artwork>
    777       </section>
    778       <section anchor="deposit">
    779         <name>Deposit</name>
    780         <t>// todo: add introductory text</t>
    781         <t>Deposit could also be used directly by a wallet with its own payto and a minimal contract.</t>
    782         <artwork><![CDATA[
    783             merchant                                 exchange
    784 Knows exchange.pub                      Knows exchange.priv
    785 Knows merchant.priv                     Knows ⟨denomᵢ⟩
    786 Knows payto, wire_salt                                  |
    787 Knows contract, ⟨depositᵢ⟩                              |
    788                |                                        |
    789 +--------------------------+                            |
    790 | (M1) deposit preparation |                            |
    791 +--------------------------+                            |
    792                |                                        |
    793                |----------- /batch-deposit ------------>|
    794                |    (info, h_contract, ⟨depositᵢ⟩       |
    795                |           merchant.pub, sig)           |
    796                |                                        |
    797                |                      +-------------------------+
    798                |                      | (E1) deposit validation |
    799                |                      +-------------------------+
    800                |                                        |
    801                |<--- (timestamp, exchange.pub, sig) ----|
    802                |                                        |
    803 +---------------------------+                           |
    804 | (M2) deposit verification |                           |
    805 +---------------------------+                           |
    806                |                                        |
    807 ]]></artwork>
    808         <t>where (without age restriction, policy and wallet data hash)</t>
    809         <artwork><![CDATA[
    810 (M1) Deposit preparation (merchant)
    811 
    812 info.time = contract.{timestamp, wire_deadline, refund_deadline}
    813 info.wire = (payto, wire_salt)
    814 h_contract = SHA-512(canonicalJSON(contract))
    815 msg = Gen-Msg(MERCHANT_CONTRACT, h_contract)
    816 sig = Ed25519-Sign(merchant.priv, msg)
    817 ]]></artwork>
    818         <artwork><![CDATA[
    819 (E1) Deposit validation (exchange)
    820 
    821 h_wire = HKDF(info.wire.wire_salt, info.wire.payto, "merchant-wire-signature", 64)
    822 for i in 0..n:
    823   coinᵢ = depositᵢ.coin
    824   denomᵢ = Lookup by coinᵢ.h_denom
    825   Check denomᵢ known and not deposit-expired
    826   totalᵢ = depositᵢ.contribution + denomᵢ.fee_deposit
    827   msgᵢ = Gen-Msg(WALLET_COIN_DEPOSIT,
    828       ( h_contract | uint256(0x0)
    829       | uint512(0x0) | h_wire | coinᵢ.h_denom
    830       | info.time.timestamp | info.time.refund_deadline
    831       | totalᵢ
    832       | denomᵢ.fee_deposit | merchant.pub | uint512(0x0) ))
    833   Check Ed25519-Verify(coinᵢ.pub, msgᵢ, depositᵢ.sig)
    834   Check RSA-FDH-Verify(SHA-512(coinᵢ.pub), coinᵢ.sig, denomᵢ.pub)
    835   Check-Subtract(coinᵢ.value, total)
    836 Persist deposit-record
    837 schedule bank transfer to payto
    838 timestamp = now()
    839 msg = Gen-Msg(EXCHANGE_CONFIRM_DEPOSIT,
    840     ( h_contract | h_wire | uint512(0x0)
    841     | timestamp | info.time.wire_deadline
    842     | info.time.refund_deadline
    843     | Sum ⟨depositᵢ.contribution⟩
    844     | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
    845 sig = Ed25519-Sign(exchange.priv, msg)
    846 ]]></artwork>
    847         <artwork><![CDATA[
    848 (M2) Deposit verification (merchant)
    849 
    850 h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64)
    851 msg = Gen-Msg(EXCHANGE_CONFIRM_DEPOSIT,
    852     ( h_contract | h_wire | uint512(0x0)
    853     | timestamp | contract.wire_deadline
    854     | contract.refund_deadline
    855     | Sum ⟨depositᵢ.contribution⟩
    856     | SHA-512( ⟨depositᵢ.sig⟩ ) | merchant.pub ))
    857 Check Ed25519-Verify(exchange.pub, msg, sig)
    858 ]]></artwork>
    859       </section>
    860       <section anchor="refresh">
    861         <name>Refresh</name>
    862         <t>The wallet obtains <tt>n</tt> new coins <tt>⟨coinᵢ⟩</tt> of denominations <tt>⟨denomᵢ⟩</tt>
    863 in exchange for one old <tt>coin</tt> of denomination <tt>denom</tt> from the exchange.
    864 There are two reasons why a wallet needs to do this:</t>
    865         <ol spacing="normal" type="1"><li>
    866             <t>Obtaining unlinkable change after using only a part of the coin's value during a payment (cf. <xref target="payment"/>) or deposit (cf. <xref target="deposit"/>),
    867 i.e. where <tt>contribution &lt;= denom.value</tt></t>
    868           </li>
    869           <li>
    870             <t>Renewing a coin before it deposit-expires.</t>
    871           </li>
    872         </ol>
    873         <t>The sum of the refresh fee of <tt>denom</tt> and the new denominations' values and withdrawal fees (defined by the exchange)
    874 must be smaller or equal to the residual value of the old <tt>coin</tt>.</t>
    875         <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>
    876 via a 512-bit secret <tt>⟨sharedₖᵢ⟩</tt> according to <tt>Refresh-Derive</tt>.
    877 The secret is regeneratable with the knowledge of <tt>coin.priv</tt> via the link protocol (cf. <xref target="link"/>).
    878 The derivation ensures that ownership of coins (knowledge of the private key) is correctly transferred,
    879 and thereby that value transfer among untrusted parties can only happen via payment and deposit, not via refresh.</t>
    880         <artwork><![CDATA[
    881 Refresh-Derive(shared, denom) =
    882   planchet_seed = HKDF(uint32(i), shared, "taler-coin-derivation", 64)
    883   blind_secret = HKDF("bks", planchet_seed, "", 32)
    884   coin.priv = HKDF("coin", planchet_seed, "", 32)
    885   coin.pub = Ed25519-GetPub(coin.priv)
    886   planchet = RSA-FDH-Blind(SHA-512(coin.pub), blind_secret, denomᵢ.pub)
    887   h_planchet = Hash-Planchet(planchet, denomᵢ)
    888   return (coin, blind_secret, planchet, h_planchet)
    889 ]]></artwork>
    890         <t>Taler uses a cut-and-choose protocol with the fixed parameter <tt>κ=3</tt> to enforce correct derivation
    891 of <tt>⟨sharedₖᵢ⟩</tt> from a single seed per batch of planchets <tt>⟨batch_seedₖ⟩</tt>
    892 (in (κ-1)/κ of the cases, making income concealment for tax evasion purposes unpractical).</t>
    893         <t>Refreshing consists of two parts:</t>
    894         <ol spacing="normal" type="1"><li>
    895             <t>Melting of the old coin and commiting to κ batches of blinded planchet candidates</t>
    896           </li>
    897           <li>
    898             <t>Revelation of κ-1 secrets <tt>⟨revealed_seedₖ⟩</tt> to prove the proper construction of the (revealed) batches of blinded planchet candidates.</t>
    899           </li>
    900         </ol>
    901         <artwork><![CDATA[
    902             wallet                                  exchange
    903 Knows ⟨denomᵢ⟩                          Knows ⟨denomᵢ.priv⟩
    904 Knows coin                                              |
    905                |                                        |
    906 +-------------------+                                   |
    907 | (W1) coin melting |                                   |
    908 +-------------------+                                   |
    909                |                                        |
    910                |---------------- /melt ---------------->|
    911                |     (coin.{pub,sig,h_denom}, value,    |
    912                |      refresh_seed, planchets, sig)     |
    913                |                                        |
    914                |                      +---------------------------------------+
    915                |                      | (E1) gamma selection and coin signing |
    916                |                      +---------------------------------------+
    917                |                                        |
    918                |<------ (ɣ, exchange.pub, sig) ---------|
    919                |                                        |
    920 +------------------------+                              |
    921 | (W2) secret revelation |                              |
    922 +------------------------+                              |
    923                |                                        |
    924                |------------ /reveal-melt ------------->|
    925                |     (commitment, ⟨revealed_seedₖ⟩)     |
    926                |                                        |
    927                |                      +----------------------------+
    928                |                      | (E2) commitment validation |
    929                |                      +----------------------------+
    930                |                                        |
    931                |<---------- (⟨blind_sigᵢ⟩) -------------|
    932                |                                        |
    933 +----------------------+                                |
    934 | (W3) coin unblinding |                                |
    935 +----------------------+                                |
    936                |                                        |
    937 ]]></artwork>
    938         <t>where (for RSA, without age-restriction)</t>
    939         <artwork><![CDATA[
    940 (W1) coin melting (wallet)
    941 
    942 refresh_seed = random(256)
    943 ⟨batch_seedₖ⟩ = HKDF("refresh-batch-seeds", refresh_seed, coin.priv, k*64)
    944 for k in 0..κ:
    945   ⟨transferₖᵢ.priv⟩ = HKDF("refresh-transfer-private-keys", batch_seedₖ, "", n*32)
    946   for i in 0..n:
    947     transferₖᵢ.pub = ECDH-GetPub(transferₖᵢ.priv)
    948     sharedₖᵢ = ECDH-Ed25519-Pub(transferₖᵢ.priv, coin.pub)
    949     (coinₖᵢ, blind_secretₖᵢ, planchetₖᵢ, h_planchetₖᵢ) = Refresh-Derive(sharedₖᵢ, denomᵢ)
    950   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
    951 value = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
    952 commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
    953                     | SHA-512( ⟨h_planchetsₖ⟩ ) )
    954 for i in 0..n:
    955   h_denomᵢ = Hash-Denom(denomᵢ)
    956 planchets = (⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩))
    957 msg = Gen-Msg(WALLET_COIN_MELT,
    958     ( commitment | coin.h_denom | uint256(0x0)
    959     | value | denom.fee_refresh ))
    960 sig = Ed25519-Sign(coin.priv, msg)
    961 Persist (coin.denom.pub, ...) // todo: double-check
    962 ]]></artwork>
    963         <artwork><![CDATA[
    964 (E1) gamma selection and coin signing (exchange)
    965 
    966 denom = Lookup by coin.h_denom
    967 Check denom known and not deposit-expired
    968 Check RSA-FDH-Verify(SHA-512(coin.pub), coin.sig, denom.pub)
    969 Check coin.pub known and dirty
    970 (⟨h_denomᵢ⟩, ⟨planchetₖᵢ⟩, ⟨transferₖᵢ.pub⟩)) = planchets
    971 for i in 0..n:
    972   denomᵢ = Lookup by h_denomᵢ
    973   Check denomᵢ known and not withdraw-expired
    974 value' = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
    975 Check value' == value
    976 Check-Subtract(coin.value, value)
    977 for k in 0..κ:
    978   for i in 0..n:
    979     h_planchetₖᵢ = Hash-Planchet(planchetₖᵢ, denomᵢ)
    980   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
    981 commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
    982                     | SHA-512( ⟨h_planchetsₖ⟩ ) )
    983 msg = Gen-Msg(WALLET_COIN_MELT,
    984     ( commitment | coin.h_denom | uint256(0x0)
    985     | value | denom.fee_refresh ))
    986 Check Ed25519-Verify(coin.pub, msg, sig)
    987 refresh_record = Lookup by commitment
    988 (ɣ, _, _, done, _) = refresh_record
    989 if refresh_record not found:
    990   ɣ = 0..κ at random
    991   for i in 0..n:
    992     blind_sigᵢ = RSA-FDH-Sign(planchetᵧᵢ, denomᵧᵢ.priv)
    993   link_info = (refresh_seed, ⟨transferₖᵢ.pub⟩, ⟨h_denomᵢ⟩, coin_sig)
    994   Persist refresh_record = (commitment, ɣ, ⟨blind_sigᵢ⟩, h_planchetsᵧ, false, link_info)
    995 msg = Gen-Msg(EXCHANGE_CONFIRM_MELT,
    996     ( commitment | uint32(ɣ) ))
    997 sig = Ed25519-Sign(exchange.priv, msg)
    998 ]]></artwork>
    999         <artwork><![CDATA[
   1000 (W2) secret revelation (wallet)
   1001 
   1002 Check exchange.pub known
   1003 msg = Gen-Msg(EXCHANGE_CONFIRM_MELT,
   1004     ( commitment | ɣ ))
   1005 Check Ed25519-Verify(exchange.pub, msg, sig)
   1006 Persist refresh-challenge // what exactly?
   1007 for k in 0..κ and k != ɣ:
   1008   revealed_seedₖ = batch_seedₖ
   1009 ]]></artwork>
   1010         <artwork><![CDATA[
   1011 (E2) commitment validation (exchange)
   1012 
   1013 refresh_record = Lookup by commitment
   1014 (ɣ, ⟨blind_sigᵢ⟩, h_planchetsᵧ, done, _) = refresh_record
   1015 Check not done // todo: sure?
   1016 for k in 0..κ and k != ɣ:
   1017   ⟨transferₖᵢ.priv⟩ = HKDF("refresh-transfer-private-keys", batch_seedₖ, "", n*32)
   1018   for i in 0..n:
   1019     transferₖᵢ.pub = ECDH-GetPub(transferₖᵢ.priv)
   1020     sharedₖᵢ = ECDH-Ed25519-Pub(transferₖᵢ.priv, coin.pub)
   1021     (_, _, _, h_planchetₖᵢ) = Refresh-Derive(sharedₖᵢ, denomᵢ)
   1022   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
   1023 value = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
   1024 commitment' = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
   1025                      | SHA-512( ⟨h_planchetsₖ⟩ ) )
   1026 Check commitment == commitment'
   1027 Persist refresh_record = (_, _, _, true, _)
   1028 ]]></artwork>
   1029         <artwork><![CDATA[
   1030 (W3) coin unblinding (wallet)
   1031 
   1032 for i in 0..n:
   1033   coinᵧᵢ.sig = RSA-FDH-Unblind(blind_sigᵧᵢ, blind_secretᵧᵢ, denomᵢ.pub)
   1034   Check RSA-FDH-Verify(SHA-512(coinᵧᵢ.pub), coinᵧᵢ.sig, denomᵢ.pub)
   1035   coinᵧᵢ.h_denom = h_denomᵢ
   1036   Persist ⟨coinᵧᵢ⟩
   1037 ]]></artwork>
   1038         <section anchor="link">
   1039           <name>Link</name>
   1040           <t>// todo: add introductory text</t>
   1041           <artwork><![CDATA[
   1042             wallet                                  exchange
   1043 Knows coin                              Knows refresh_record for coin
   1044                |                                        |
   1045 +----------------------+                                |
   1046 | (W1) history request |                                |
   1047 +----------------------+                                |
   1048                |                                        |
   1049                |------ /coins/{coin.pub}/history ------>|
   1050                |                 (sig)                  |
   1051                |                                        |
   1052                |                      +----------------------------+
   1053                |                      | (E1) refresh secret lookup |
   1054                |                      +----------------------------+
   1055                |                                        |
   1056                |<------------- (melt_info) -------------|
   1057                |                                        |
   1058 +-----------------------+                               |
   1059 | (W2) coin acquisition |                               |
   1060 +-----------------------+                               |
   1061                |                                        |
   1062 ]]></artwork>
   1063           <t>where (for RSA, without age-restriction)</t>
   1064           <artwork><![CDATA[
   1065 (W1) history request (wallet)
   1066 
   1067 msg = Gen-Msg(COIN_HISTORY_REQUEST, uint64(0x0))
   1068 sig = Ed25519-Sign(coin.priv, msg)
   1069 ]]></artwork>
   1070           <artwork><![CDATA[
   1071 (E1) refresh secret lookup (exchange)
   1072 
   1073 refresh_record = Lookup by coin.pub
   1074 (ɣ, ⟨blind_sigᵢ⟩, _, done, link_info) = refresh_record
   1075 if done:
   1076   melt_info = (ɣ, link_info, ⟨blind_sigᵢ⟩)
   1077 else:
   1078   melt_info = (ɣ, link_info)
   1079 ]]></artwork>
   1080           <artwork><![CDATA[
   1081 (W2) coin acquisition (wallet)
   1082 
   1083 (ɣ, link_info, ⟨blind_sigᵢ⟩?) = melt_info
   1084 (refresh_seed, ⟨transferₖᵢ.pub⟩, ⟨h_denomᵢ⟩, coin_sig) = link_info
   1085 
   1086 for i in 0..n:
   1087   denomᵢ = Lookup by h_denomᵢ
   1088 for k in 0..κ:
   1089   for i in 0..n:
   1090     sharedₖᵢ = ECDH-Ed25519-Priv(coin.priv, transferₖᵢ.pub)
   1091     (coinₖᵢ, blind_secretₖᵢ _, h_planchetₖᵢ) = Refresh-Derive(sharedₖᵢ, denomᵢ)
   1092   h_planchetsₖ = SHA-512( ⟨h_planchetₖᵢ⟩ )
   1093 value = coin.denom.fee_refresh + Sum ⟨denomᵢ.value⟩ + Sum ⟨denomᵢ.fee_withdraw⟩
   1094 commitment = SHA-512( refresh_seed | uint256(0x0) | coin.pub | value
   1095                     | SHA-512( ⟨h_planchetsₖ⟩ ) )
   1096 msg = Gen-Msg(WALLET_COIN_MELT,
   1097     ( commitment | coin.h_denom | uint256(0x0)
   1098     | value | denom.fee_refresh ))
   1099 Check Ed25519-Verify(coin.pub, msg, sig)
   1100 
   1101 if ⟨blind_sigᵢ⟩ returned:
   1102   for i in 0..n:
   1103     coinᵧᵢ.sig = RSA-FDH-Unblind(blind_sigᵧᵢ, blind_secretᵧᵢ, denomᵢ.pub)
   1104     Check RSA-FDH-Verify(SHA-512(coinᵧᵢ.pub), coinᵧᵢ.sig, denomᵢ.pub)
   1105     coinᵧᵢ.h_denom = h_denomᵢ
   1106   Persist ⟨coinᵧᵢ⟩
   1107 ]]></artwork>
   1108         </section>
   1109       </section>
   1110       <section anchor="refund">
   1111         <name>Refund</name>
   1112         <t>// todo</t>
   1113       </section>
   1114       <section anchor="recoup">
   1115         <name>Recoup</name>
   1116         <t>// todo</t>
   1117       </section>
   1118       <section anchor="w2w-push">
   1119         <name>Wallet-to-Wallet Push Payment</name>
   1120         <t>// todo</t>
   1121       </section>
   1122       <section anchor="w2w-pull">
   1123         <name>Wallet-to-Wallet Pull Payment</name>
   1124         <t>// todo</t>
   1125       </section>
   1126     </section>
   1127     <section anchor="security-considerations">
   1128       <name>Security Considerations</name>
   1129       <t>[ TBD ]</t>
   1130     </section>
   1131     <section anchor="iana-considerations">
   1132       <name>IANA Considerations</name>
   1133       <t>None.</t>
   1134     </section>
   1135   </middle>
   1136   <back>
   1137     <references anchor="sec-normative-references">
   1138       <name>Normative References</name>
   1139       <reference anchor="RFC20">
   1140         <front>
   1141           <title>ASCII format for network interchange</title>
   1142           <author fullname="V.G. Cerf" initials="V.G." surname="Cerf"/>
   1143           <date month="October" year="1969"/>
   1144         </front>
   1145         <seriesInfo name="STD" value="80"/>
   1146         <seriesInfo name="RFC" value="20"/>
   1147         <seriesInfo name="DOI" value="10.17487/RFC0020"/>
   1148       </reference>
   1149       <reference anchor="RFC2104">
   1150         <front>
   1151           <title>HMAC: Keyed-Hashing for Message Authentication</title>
   1152           <author fullname="H. Krawczyk" initials="H." surname="Krawczyk"/>
   1153           <author fullname="M. Bellare" initials="M." surname="Bellare"/>
   1154           <author fullname="R. Canetti" initials="R." surname="Canetti"/>
   1155           <date month="February" year="1997"/>
   1156           <abstract>
   1157             <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>
   1158           </abstract>
   1159         </front>
   1160         <seriesInfo name="RFC" value="2104"/>
   1161         <seriesInfo name="DOI" value="10.17487/RFC2104"/>
   1162       </reference>
   1163       <reference anchor="RFC5869">
   1164         <front>
   1165           <title>HMAC-based Extract-and-Expand Key Derivation Function (HKDF)</title>
   1166           <author fullname="H. Krawczyk" initials="H." surname="Krawczyk"/>
   1167           <author fullname="P. Eronen" initials="P." surname="Eronen"/>
   1168           <date month="May" year="2010"/>
   1169           <abstract>
   1170             <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>
   1171           </abstract>
   1172         </front>
   1173         <seriesInfo name="RFC" value="5869"/>
   1174         <seriesInfo name="DOI" value="10.17487/RFC5869"/>
   1175       </reference>
   1176       <reference anchor="RFC6234">
   1177         <front>
   1178           <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
   1179           <author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake 3rd"/>
   1180           <author fullname="T. Hansen" initials="T." surname="Hansen"/>
   1181           <date month="May" year="2011"/>
   1182           <abstract>
   1183             <t>Federal Information Processing Standard, FIPS</t>
   1184           </abstract>
   1185         </front>
   1186         <seriesInfo name="RFC" value="6234"/>
   1187         <seriesInfo name="DOI" value="10.17487/RFC6234"/>
   1188       </reference>
   1189       <reference anchor="RFC7748">
   1190         <front>
   1191           <title>Elliptic Curves for Security</title>
   1192           <author fullname="A. Langley" initials="A." surname="Langley"/>
   1193           <author fullname="M. Hamburg" initials="M." surname="Hamburg"/>
   1194           <author fullname="S. Turner" initials="S." surname="Turner"/>
   1195           <date month="January" year="2016"/>
   1196           <abstract>
   1197             <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>
   1198           </abstract>
   1199         </front>
   1200         <seriesInfo name="RFC" value="7748"/>
   1201         <seriesInfo name="DOI" value="10.17487/RFC7748"/>
   1202       </reference>
   1203       <reference anchor="RFC8032">
   1204         <front>
   1205           <title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
   1206           <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
   1207           <author fullname="I. Liusvaara" initials="I." surname="Liusvaara"/>
   1208           <date month="January" year="2017"/>
   1209           <abstract>
   1210             <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>
   1211           </abstract>
   1212         </front>
   1213         <seriesInfo name="RFC" value="8032"/>
   1214         <seriesInfo name="DOI" value="10.17487/RFC8032"/>
   1215       </reference>
   1216       <reference anchor="HKDF">
   1217         <front>
   1218           <title>Cryptographic Extraction and Key Derivation: The HKDF Scheme</title>
   1219           <author fullname="Hugo Krawczyk" initials="H." surname="Krawczyk">
   1220             <organization/>
   1221           </author>
   1222           <date year="2010"/>
   1223         </front>
   1224         <seriesInfo name="Lecture Notes in Computer Science" value="pp. 631-648"/>
   1225         <seriesInfo name="DOI" value="10.1007/978-3-642-14623-7_34"/>
   1226         <seriesInfo name="ISBN" value="[&quot;9783642146220&quot;, &quot;9783642146237&quot;]"/>
   1227         <refcontent>Springer Berlin Heidelberg</refcontent>
   1228       </reference>
   1229       <reference anchor="SHS">
   1230         <front>
   1231           <title>Secure hash standard</title>
   1232           <author>
   1233             <organization/>
   1234           </author>
   1235           <date year="2015"/>
   1236         </front>
   1237         <seriesInfo name="DOI" value="10.6028/nist.fips.180-4"/>
   1238         <refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
   1239       </reference>
   1240     </references>
   1241     <?line 1250?>
   1242 
   1243 <section anchor="change-log">
   1244       <name>Change log</name>
   1245     </section>
   1246     <section numbered="false" anchor="acknowledgments">
   1247       <name>Acknowledgments</name>
   1248       <t>[ TBD ]</t>
   1249       <t>This work was supported in part by the German Federal Ministry of
   1250 Education and Research (BMBF) within the project Concrete Contracts.</t>
   1251     </section>
   1252   </back>
   1253   <!-- ##markdown-source:
   1254 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
   1470 uSZK6w9UFpouS8y7b7Q+eNfV6+EGq64NwD+3doDgI0Db3O7GdhDoIk9Wxcpl
   1471 itlWf847CEg+lxQducIffe9gzWtl9O2WfvDP0yiPPuNrZa65d1A1TCtSznWt
   1472 sOhsHQWzjx6fnD47/rl3fPgPLw5PTttC/TwP2uq1klnzdnNFCqqZ29f2XllX
   1473 LPZdTbhbRmqNYS82QttquBjdAhzU9Gsav+VICAOX97smThq5tqTZapi+xwUa
   1474 cJybiJ5hQDNlgz+yKiW2VjZpqVONv5lucdr8CtbK7f/Hdbf/KyFmx/Ioz/Ny
   1475 oeoNZbiAAT+OV33TfvVNeNbI8FMIvqkAHz6UzrV6G6Qgw/gWP9TevuS7povU
   1476 40/i+RTIU95pebl96U2mVNS/olscz3WL40o3/LnxaRYVM/xl9jwK1UUnueP8
   1477 /pU4/eFA/P41tnqMP59Wb3EECr3jOOiaDPzgHNvtc+V9nA7x216gC5Tph+NB
   1478 B/MPcslwd4OyexvvKvPQ7eOXaXYOkQVeBkO/Mc53zFDhvipTfyizsZ+IBxJh
   1479 icVTzLAVGVaYO4cQsJSXbB/LXPpZMBLuD09/eNAic19ebYM/wIFrQt6S+IFy
   1480 9XnH+f9L/aigpJ4AAA==
   1481 
   1482 -->
   1483 
   1484 </rfc>