draft-guetschow-taler-protocol.xml (37834B)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> 3 <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.17 (Ruby 3.1.2) --> 4 5 6 <!DOCTYPE rfc [ 7 <!ENTITY nbsp " "> 8 <!ENTITY zwsp "​"> 9 <!ENTITY nbhy "‑"> 10 <!ENTITY wj "⁠"> 11 12 ]> 13 14 15 <rfc ipr="trust200902" docName="draft-guetschow-taler-protocol" category="info" submissionType="independent" tocInclude="true" sortRefs="true" symRefs="true"> 16 <front> 17 <title>The GNU Taler Protocol</title> 18 19 <author initials="M." surname="Gütschow" fullname="Mikolai Gütschow"> 20 <organization abbrev="TU Dresden">TUD Dresden University of Technology</organization> 21 <address> 22 <postal> 23 <street>Helmholtzstr. 10</street> 24 <city>Dresden</city> 25 <code>D-01069</code> 26 <country>Germany</country> 27 </postal> 28 <email>mikolai.guetschow@tu-dresden.de</email> 29 </address> 30 </author> 31 32 <date year="2025" month="August" day="12"/> 33 34 35 <workgroup>independent</workgroup> 36 <keyword>taler</keyword> <keyword>cryptography</keyword> <keyword>ecash</keyword> <keyword>payments</keyword> 37 38 <abstract> 39 40 41 <?line 43?> 42 43 <t>[ TBW ]</t> 44 45 46 47 </abstract> 48 49 50 51 </front> 52 53 <middle> 54 55 56 <?line 47?> 57 58 <section anchor="introduction"><name>Introduction</name> 59 60 <t>[ TBW ]</t> 61 62 <t>Beware that this document is still work-in-progress and may contain errors. 63 Use at your own risk!</t> 64 65 </section> 66 <section anchor="notation"><name>Notation</name> 67 68 <t><list style="symbols"> 69 <t><spanx style="verb">"abc"</spanx> denotes the literal string <spanx style="verb">abc</spanx> encoded as ASCII <xref target="RFC20"></xref></t> 70 <t><spanx style="verb">a | b</spanx> denotes the concatenation of a with b</t> 71 <t><spanx style="verb">len(a)</spanx> denotes the length in bytes of the byte string a</t> 72 <t><spanx style="verb">padZero(y, a)</spanx> denotes the byte string a, zero-padded to the length of y bytes</t> 73 <t><spanx style="verb">bits(x)</spanx>/<spanx style="verb">bytes(x)</spanx> denotes the minimal number of bits/bytes necessary to represent the multiple precision integer x</t> 74 <t><spanx style="verb">uint(y, x)</spanx> denotes the <spanx style="verb">y</spanx> least significant bits of the integer <spanx style="verb">x</spanx> encoded in network byte order (big endian)</t> 75 <t><spanx style="verb">uint16(x)</spanx>/<spanx style="verb">uint32(x)</spanx>/<spanx style="verb">uint64(x)</spanx>/<spanx style="verb">uint256(x)</spanx>/<spanx style="verb">uint512(x)</spanx> is equivalent to <spanx style="verb">uint(16, x)</spanx>/<spanx style="verb">uint(32, x)</spanx>/<spanx style="verb">uint(64, x)</spanx>/<spanx style="verb">uint(256, x)</spanx>/<spanx style="verb">uint(512, x)</spanx>, respectively</t> 76 <t><spanx style="verb">random(y)</spanx> denotes a randomly generated sequence of y bits</t> 77 <t><spanx style="verb">a * b (mod N)</spanx> / <spanx style="verb">a ** b (mod N)</spanx> denotes the multiplication / exponentiation of multiple precision integers a and b, modulo N</t> 78 </list></t> 79 80 </section> 81 <section anchor="cryptographic-primitives"><name>Cryptographic Primitives</name> 82 83 <section anchor="cryptographic-hash-functions"><name>Cryptographic Hash Functions</name> 84 85 <section anchor="sha256"><name>SHA-256</name> 86 87 <figure><artwork><![CDATA[ 88 SHA-256(msg) -> hash 89 90 Input: 91 msg input message of length L < 2^61 octets 92 93 Output: 94 hash message digest of fixed length HashLen = 32 octets 95 ]]></artwork></figure> 96 97 <t><spanx style="verb">hash</spanx> is the output of SHA-256 as per Sections 4.1, 5.1, 6.1, and 6.2 of <xref target="RFC6234"></xref>.</t> 98 99 </section> 100 <section anchor="sha512"><name>SHA-512</name> 101 102 <figure><artwork><![CDATA[ 103 SHA-512(msg) -> hash 104 105 Input: 106 msg input message of length L < 2^125 octets 107 108 Output: 109 hash message digest of fixed length HashLen = 64 octets 110 ]]></artwork></figure> 111 112 <t><spanx style="verb">hash</spanx> is the output of SHA-512 as per Sections 4.2, 5.2, 6.3, and 6.4 of <xref target="RFC6234"></xref>.</t> 113 114 </section> 115 <section anchor="sha512-trunc"><name>SHA-512-256 (truncated SHA-512)</name> 116 117 <figure><artwork><![CDATA[ 118 SHA-512-256(msg) -> hash 119 120 Input: 121 msg input message of length L < 2^125 octets 122 123 Output: 124 hash message digest of fixed length HashLen = 32 octets 125 ]]></artwork></figure> 126 127 <t>The output <spanx style="verb">hash</spanx> corresponds to the first 32 octets of the output of SHA-512 defined in <xref target="sha512"/>:</t> 128 129 <figure><artwork><![CDATA[ 130 temp = SHA-512(msg) 131 hash = temp[0:31] 132 ]]></artwork></figure> 133 134 <t>Note that this operation differs from SHA-512/256 as defined in <xref target="SHS"></xref> in the initial hash value.</t> 135 136 </section> 137 </section> 138 <section anchor="message-authentication-codes"><name>Message Authentication Codes</name> 139 140 <section anchor="hmac"><name>HMAC</name> 141 142 <figure><artwork><![CDATA[ 143 HMAC-Hash(key, text) -> out 144 145 Option: 146 Hash cryptographic hash function with output length HashLen 147 148 Input: 149 key secret key of length at least HashLen 150 text input data of arbitary length 151 152 Output: 153 out output of length HashLen 154 ]]></artwork></figure> 155 156 <t><spanx style="verb">out</spanx> is calculated as defined in <xref target="RFC2104"></xref>.</t> 157 158 </section> 159 </section> 160 <section anchor="key-derivation-functions"><name>Key Derivation Functions</name> 161 162 <section anchor="hkdf"><name>HKDF</name> 163 164 <t>The Hashed Key Derivation Function (HKDF) used in Taler is an instantiation of <xref target="RFC5869"></xref> 165 with two different hash functions for the Extract and Expand step as suggested in <xref target="HKDF"></xref>: 166 <spanx style="verb">HKDF-Extract</spanx> uses <spanx style="verb">HMAC-SHA512</spanx>, while <spanx style="verb">HKDF-Expand</spanx> uses <spanx style="verb">HMAC-SHA256</spanx> (cf. <xref target="hmac"/>).</t> 167 168 <figure><artwork><![CDATA[ 169 HKDF(salt, IKM, info, L) -> OKM 170 171 Inputs: 172 salt optional salt value (a non-secret random value); 173 if not provided, it is set to a string of 64 zeros. 174 IKM input keying material 175 info optional context and application specific information 176 (can be a zero-length string) 177 L length of output keying material in octets 178 (<= 255*32 = 8160) 179 180 Output: 181 OKM output keying material (of L octets) 182 ]]></artwork></figure> 183 184 <t>The output OKM is calculated as follows:</t> 185 186 <figure><artwork><![CDATA[ 187 PRK = HKDF-Extract(salt, IKM) with Hash = SHA-512 (HashLen = 64) 188 OKM = HKDF-Expand(PRK, info, L) with Hash = SHA-256 (HashLen = 32) 189 ]]></artwork></figure> 190 191 </section> 192 <section anchor="hkdf-mod"><name>HKDF-Mod</name> 193 194 <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> 195 196 <figure><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></figure> 210 211 <t>The final output <spanx style="verb">OKM</spanx> is determined deterministically based on a counter initialized at zero.</t> 212 213 <figure><artwork><![CDATA[ 214 counter = 0 215 do until OKM < N: 216 x = HKDF(salt, IKM, info | uint16(counter), bytes(N)) 217 OKM = uint(bits(N), x) 218 counter += 1 219 ]]></artwork></figure> 220 221 </section> 222 </section> 223 <section anchor="non-blind-signatures"><name>Non-Blind Signatures</name> 224 225 <section anchor="ed25519"><name>Ed25519</name> 226 227 </section> 228 </section> 229 <section anchor="blind-signatures"><name>Blind Signatures</name> 230 231 <section anchor="rsa-fdh"><name>RSA-FDH</name> 232 233 <section anchor="supporting-functions"><name>Supporting Functions</name> 234 235 <figure><artwork><![CDATA[ 236 RSA-FDH(msg, pubkey) -> fdh 237 238 Inputs: 239 msg message 240 pubkey RSA public key consisting of modulus N and public exponent e 241 242 Output: 243 fdh full-domain hash of msg over pubkey.N 244 ]]></artwork></figure> 245 246 <t><spanx style="verb">fdh</spanx> is calculated based on HKDF-Mod from <xref target="hkdf-mod"/> as follows:</t> 247 248 <figure><artwork><![CDATA[ 249 info = "RSA-FDA FTpsW!" 250 salt = uint16(bytes(pubkey.N)) | uint16(bytes(pubkey.e)) 251 | pubkey.N | pubkey.e 252 fdh = HKDF-Mod(pubkey.N, salt, msg, info) 253 ]]></artwork></figure> 254 255 <t>The resulting <spanx style="verb">fdh</spanx> can be used to test against a malicious RSA pubkey 256 by verifying that the greatest common denominator (gcd) of <spanx style="verb">fdh</spanx> and <spanx style="verb">pubkey.N</spanx> is 1.</t> 257 258 <figure><artwork><![CDATA[ 259 RSA-FDH-Derive(bks, pubkey) -> out 260 261 Inputs: 262 bks blinding key secret of length L = 32 octets 263 pubkey RSA public key consisting of modulus N and public exponent e 264 265 Output: 266 out full-domain hash of bks over pubkey.N 267 ]]></artwork></figure> 268 269 <t><spanx style="verb">out</spanx> is calculated based on HKDF-Mod from <xref target="hkdf-mod"/> as follows:</t> 270 271 <figure><artwork><![CDATA[ 272 info = "Blinding KDF" 273 salt = "Blinding KDF extractor HMAC key" 274 fdh = HKDF-Mod(pubkey.N, salt, bks, info) 275 ]]></artwork></figure> 276 277 </section> 278 <section anchor="blinding"><name>Blinding</name> 279 280 <figure><artwork><![CDATA[ 281 RSA-FDH-Blind(msg, bks, pubkey) -> out 282 283 Inputs: 284 msg message 285 bks blinding key secret of length L = 32 octets 286 pubkey RSA public key consisting of modulus N and public exponent e 287 288 Output: 289 out message blinded for pubkey 290 ]]></artwork></figure> 291 292 <t><spanx style="verb">out</spanx> is calculated based on RSA-FDH from <xref target="rsa-fdh"/> as follows:</t> 293 294 <figure><artwork><![CDATA[ 295 data = RSA-FDH(msg, pubkey) 296 r = RSA-FDH-Derive(bks, pubkey) 297 r_e = r ** pubkey.e (mod pubkey.N) 298 out = r_e * data (mod pubkey.N) 299 ]]></artwork></figure> 300 301 </section> 302 <section anchor="signing"><name>Signing</name> 303 304 <figure><artwork><![CDATA[ 305 RSA-FDH-Sign(data, privkey) -> sig 306 307 Inputs: 308 data data to be signed, an integer smaller than privkey.N 309 privkey RSA private key consisting of modulus N and private exponent d 310 311 Output: 312 sig signature on data by privkey 313 ]]></artwork></figure> 314 315 <t><spanx style="verb">sig</spanx> is calculated as follows:</t> 316 317 <figure><artwork><![CDATA[ 318 sig = data ** privkey.d (mod privkey.N) 319 ]]></artwork></figure> 320 321 </section> 322 <section anchor="unblinding"><name>Unblinding</name> 323 324 <figure><artwork><![CDATA[ 325 RSA-FDH-Unblind(sig, bks, pubkey) -> out 326 327 Inputs: 328 sig blind signature 329 bks blinding key secret of length L = 32 octets 330 pubkey RSA public key consisting of modulus N and public exponent e 331 332 Output: 333 out unblinded signature 334 ]]></artwork></figure> 335 336 <t><spanx style="verb">out</spanx> is calculated as follows:</t> 337 338 <figure><artwork><![CDATA[ 339 r = RSA-FDH-Derive(bks, pubkey) 340 r_inv = inverse of r (mod pubkey.N) 341 out = sig * r_inv (mod pubkey.N) 342 ]]></artwork></figure> 343 344 </section> 345 <section anchor="verifying"><name>Verifying</name> 346 347 <figure><artwork><![CDATA[ 348 RSA-FDH-Verify(msg, sig, pubkey) -> out 349 350 Inputs: 351 msg message 352 sig signature of pubkey over msg 353 pubkey RSA public key consisting of modulus N and public exponent e 354 355 Output: 356 out true, if sig is a valid signature 357 ]]></artwork></figure> 358 359 <t><spanx style="verb">out</spanx> is calculated based on RSA-FDH from <xref target="rsa-fdh"/> as follows:</t> 360 361 <figure><artwork><![CDATA[ 362 data = RSA-FDH(msg, pubkey) 363 exp = sig ** pubkey.e (mod pubkey.N) 364 out = (data == exp) 365 ]]></artwork></figure> 366 367 </section> 368 </section> 369 <section anchor="clause-schnorr"><name>Clause-Schnorr</name> 370 371 </section> 372 </section> 373 </section> 374 <section anchor="the-taler-crypto-protocol"><name>The Taler Crypto Protocol</name> 375 376 <section anchor="datatypes"><name>Datatypes</name> 377 378 <section anchor="amount"><name>Amount</name> 379 380 <t>Amounts are represented in Taler as positive fixed-point values 381 consisting of <spanx style="verb">value</spanx> as the non-negative integer part of the base currency, 382 the <spanx style="verb">fraction</spanx> given in units of one hundred millionth (1e-8) of the base currency, 383 and <spanx style="verb">currency</spanx> as the 3-11 ASCII characters identifying the currency.</t> 384 385 <t>Whenever used in the protocol, the binary representation of an <spanx style="verb">amount</spanx> is 386 <spanx style="verb">uint64(amount.value) | uint32(amount.fraction) | padZero(12, amount.currency)</spanx>.</t> 387 388 </section> 389 <section anchor="timestamps"><name>Timestamps</name> 390 391 <t>Absolute timestamps are represented as <spanx style="verb">uint64(x)</spanx> where <spanx style="verb">x</spanx> corresponds to 392 the microseconds since <spanx style="verb">1970-01-01 00:00 CEST</spanx> (the UNIX epoch). 393 The special value <spanx style="verb">0xFFFFFFFFFFFFFFFF</spanx> represents "never". 394 <!-- 395 // todo: check if needed and correct 396 Relative timestamps are represented as `uint64(x)` where `x` is given in microseconds. 397 The special value `0xFFFFFFFFFFFFFFFF` represents "forever". 398 --></t> 399 400 </section> 401 <section anchor="signatures"><name>Signatures</name> 402 403 <t>All messages to be signed in Taler start with a header containing their size and 404 a fixed signing context (purpose) as registered by GANA in the 405 <eref target="https://gana.gnunet.org/gnunet-signatures/gnunet_signatures.html">GNUnet Signature Purposes</eref> 406 registry. All Taler-related purposes start at 1000 and can be found in the 407 <eref target="https://git.taler.net/gana.git/tree/gnunet-signatures/registry.rec#n221">registry sources</eref>.</t> 408 409 <figure><artwork><![CDATA[ 410 Sign-Msg(purpose, msg) -> out 411 412 Inputs: 413 purpose signature purpose as registered at GANA 414 msg message content (excl. header) to be signed 415 416 Output: 417 out complete message (incl. header) to be signed 418 ]]></artwork></figure> 419 420 <t><spanx style="verb">out</spanx> is formed as follows:</t> 421 422 <figure><artwork><![CDATA[ 423 out = uint32(len(msg)) | uint32(purpose) | msg 424 ]]></artwork></figure> 425 426 <t>// todo: explain persist, check, knows, sum</t> 427 428 </section> 429 </section> 430 <section anchor="withdrawal"><name>Withdrawal</name> 431 432 <t>The wallet generates <spanx style="verb">n > 0</spanx> coins (<spanx style="verb">coin[i]</spanx>) and requests <spanx style="verb">n</spanx> signatures (<spanx style="verb">blind_sig[i]</spanx>) from the exchange, 433 attributing value to the coins according to <spanx style="verb">n</spanx> chosen denominations (<spanx style="verb">denom[i]</spanx>). 434 The total value and withdrawal fee (defined by the exchange per denomination) 435 must be smaller or equal to the amount stored in the single reserve used for withdrawal.</t> 436 437 <figure><artwork><![CDATA[ 438 wallet exchange 439 knows denom[i].pub knows denom[i].priv 440 | | 441 +----------------------------+ | 442 | (1) reserve key generation | | 443 +----------------------------+ | 444 | | 445 |----------- (bank transfer) ----------->| 446 | (subject: reserve.pub, amount: value) | 447 | | 448 | +------------------------------+ 449 | | persist (reserve.pub, value) | 450 | +------------------------------+ 451 | | 452 +----------------------------------+ | 453 | (2) coin generation and blinding | | 454 +----------------------------------+ | 455 | | 456 |-------------- /withdraw -------------->| 457 | (reserve.pub, coin[i].h_denom, | 458 | blind_coin[i], sig0) | 459 | | 460 | +-------------------------------+ 461 | | (3) coin issuance and signing | 462 | +-------------------------------+ 463 | | 464 |<----------- blind_sig[i] --------------| 465 | | 466 +---------------------+ | 467 | (4) coin unblinding | | 468 +---------------------+ | 469 ]]></artwork></figure> 470 471 <t>where (for RSA, without age-restriction)</t> 472 473 <figure><artwork><![CDATA[ 474 (1) reserve key generation (wallet) 475 476 reserve = EdDSA-Keygen() 477 persist (reserve, value) 478 ]]></artwork></figure> 479 480 <t>The wallet derives coins and blinding secrets using a HKDF from a master secret per withdrawal and an integer index. 481 This is strictly speaking an implementation detail since the master secret is never revealed to any other party, 482 and might be chosen to be implemented differently.</t> 483 484 <figure><artwork><![CDATA[ 485 (2) coin generation and blinding (wallet) 486 487 master_secret = random(256) 488 persist master_secret 489 coin_seed[i] = HKDF(uint32(i), master_secret, "taler-withdrawal-coin-derivation", 64) 490 blind_secret[i] = coin_seed[i][32:] 491 coin[i].priv = coin_seed[i][:32] 492 coin[i].pub = EdDSA-GetPub(coin[i].priv) 493 coin[i].h_denom = SHA-512(uint32(0) | uint32(1) | denom[i].pub) 494 blind_coin[i] = RSA-FDH-Blind(SHA-512(coin[i].pub), blind_secret[i], denom[i].pub) 495 msg0 = Sign-Msg(WALLET_RESERVE_WITHDRAW, 496 ( sum(denom[i].value) | sum(denom[i].fee_withdraw) 497 | SHA-512( SHA-512(denom[i].pub) | uint32(0x1) | blind_coin[i] ) 498 | uint256(0x0) | uint32(0x0) | uint32(0x0) )) 499 sig0 = EdDSA-Sign(reserve.priv, msg0) 500 ]]></artwork></figure> 501 502 <figure><artwork><![CDATA[ 503 (3) coin issuance and signing (exchange) 504 505 denom[i] = Denom-Lookup(coin[i].h_denom) 506 check denom[i].pub known and not withdrawal-expired 507 check EdDSA-Verify(reserve.pub, msg, sig) 508 check reserve KYC status ok or not needed 509 check reserve.balance >= sum(denom[i].value + denom[i].fee_withdraw) 510 reserve.balance -= sum(denom[i].value + denom[i].fee_withdraw) 511 blind_sig[i] = RSA-FDH-Sign(blind_coin[i], denom[i].priv) 512 persist withdrawal 513 ]]></artwork></figure> 514 515 <figure><artwork><![CDATA[ 516 (4) coin unblinding (wallet) 517 518 coin[i].sig = RSA-FDH-Unblind(blind_sig[i], blind_secret[i], denom[i].pub) 519 check RSA-FDH-Verify(SHA-512(coin[i].pub), coin[i].sig, denom[i].pub) 520 persist (coin[i], blind_secret[i]) 521 ]]></artwork></figure> 522 523 </section> 524 <section anchor="payment"><name>Payment</name> 525 526 <figure><artwork><![CDATA[ 527 wallet merchant 528 knows merchant.pub knows merchant.priv 529 knows valid coin[i] knows exchange, payto 530 | | 531 | +----------------------+ 532 | | (1) order generation | 533 | +----------------------+ 534 | | 535 |<-------- (order.{id,token?}) ----------| 536 | | 537 +----------------------+ | 538 | (2) nonce generation | | 539 +----------------------+ | 540 | | 541 |------- /orders/{order.id}/claim ------>| 542 | (nonce.pub, token?) | 543 | | 544 | +-------------------------+ 545 | | (3) contract generation | 546 | +-------------------------+ 547 | | 548 |<----------- contract, sig -------------| 549 | | 550 +-------------------------+ | 551 | (4) payment preparation | | 552 +-------------------------+ | 553 | | 554 |------- /orders/{order.id}/pay -------->| 555 | (deposit[i]) | 556 | | 557 | +-------------------+ 558 | | (5) deposit check | 559 | +-------------------+ 560 | | 561 |<---------------- sig ------------------| 562 | | 563 +--------------------------+ | 564 | (6) payment verification | | 565 +--------------------------+ | 566 ]]></artwork></figure> 567 568 <t>where (without age restriction, policy and wallet data hash)</t> 569 570 <figure><artwork><![CDATA[ 571 (1) order generation (merchant) 572 573 wire_salt = random(128) 574 persist order = (id, price, info, token?, wire_salt) 575 ]]></artwork></figure> 576 577 <figure><artwork><![CDATA[ 578 (2) nonce generation (wallet) 579 580 nonce = EdDSA-Keygen() 581 persist nonce.priv 582 ]]></artwork></figure> 583 584 <t>Note that the private key of <spanx style="verb">nonce</spanx> is currently not used anywhere in the protocol. 585 However, it could be used in the future to prove ownership of an order transaction, 586 enabling use-cases such as "unclaiming" or transferring an order to another person, 587 or proving the payment without resorting to the individual coins.</t> 588 589 <figure><artwork><![CDATA[ 590 (3) contract generation (merchant) 591 592 h_wire = HKDF(wire_salt, payto, "merchant-wire-signature", 64) 593 determine timestamp, refund_deadline, wire_deadline 594 contract = (order.{id,price,info,token?}, exchange, h_wire, timestamp, refund_deadline, wire_deadline) 595 check contract.order.token = token? 596 contract.nonce = nonce.pub 597 persist contract 598 h_contract = SHA-512(canonicalJSON(contract)) 599 msg = Sign-Msg(MERCHANT_CONTRACT, h_contract) 600 sig = EdDSA-Sign(merchant.priv, msg) 601 ]]></artwork></figure> 602 603 <figure><artwork><![CDATA[ 604 (4) payment preparation (wallet) 605 606 check EdDSA-Verify(merchant.pub, msg, sig) 607 check contract.nonce = nonce 608 TODO: double-check extra hash check? 609 deposit = CoinSelection(contract.{exchange,price}) TODO: include MarkDirty here 610 msg[i] = Sign-Msg(WALLET_COIN_DEPOSIT, 611 ( h_contract | uint256(0x0) 612 | uint512(0x0) | contract.h_wire | coin[i].h_denom 613 | contract.timestamp | contract.refund_deadline 614 | deposit[i] + denom[i].fee_deposit 615 | denom[i].fee_deposit | merchant.pub | uint512(0x0) )) 616 sig[i] = EdDSA-Sign(coin[i].priv, msg[i]) 617 deposit[i] = (coin[i].{pub,sig,h_denom}, fraction[i], sig[i]) 618 persist (contract, sig[i], deposit[i]) 619 ]]></artwork></figure> 620 621 <figure><artwork><![CDATA[ 622 (5) deposit check (merchant) 623 624 check sum(deposit[i].fraction) == contract.price 625 check Deposit(deposit)[i] 626 msg = Sign-Msg(MERCHANT_PAYMENT_OK, h_contract) 627 sig = EdDSA-Sign(merchant.priv, msg) 628 ]]></artwork></figure> 629 630 <figure><artwork><![CDATA[ 631 (6) payment verification 632 633 check EdDSA-Verify(merchant.pub, msg, sig) 634 ]]></artwork></figure> 635 636 </section> 637 <section anchor="deposit"><name>Deposit</name> 638 639 <figure><artwork><![CDATA[ 640 merchant/wallet exchange 641 knows exchange.pub knows exchange.priv 642 knows merchant.pub knows *denom.pub 643 knows payto, wire_salt, sig2, h_contract 644 knows contract, *deposit from Payment 645 | | 646 |----------- /batch-deposit ------------>| 647 | (contract.{timestamp,wire_deadline,refund_deadline} 648 | h_contract, merchant.pub, sig2, | 649 | payto, *deposit, wire_salt) | 650 | | 651 | *denom = Denom-Lookup(*deposit.coin.h_denom) 652 | check *denom.pub known and not deposit-expired 653 | contract.h_wire = HKDF(wire_salt, payto, 654 | "merchant-wire-signature", 64) 655 | check *EdDSA-Verify(deposit.coin.pub, msg1, sig1) 656 | check *RSA-FDH-Verify(SHA-512(deposit.coin.pub), 657 | deposit.coin.sig, denom.pub) 658 | check not overspending 659 | persist deposit-record, mark-spent 660 | schedule bank transfer 661 | exchange_timestamp = now() 662 | sig3 = EdDSA-Sign(exchange.priv, msg3) 663 | | 664 |<----- sig3, exchange_timestamp --------| 665 | | 666 check EdDSA-Verify(exchange.pub, msg3, sig3) | 667 ]]></artwork></figure> 668 669 <t>where <spanx style="verb">msg3</spanx> is formed as follows:</t> 670 671 <figure><artwork><![CDATA[ 672 msg3 = Sign-Msg(EXCHANGE_CONFIRM_DEPOSIT, 673 ( h_contract | contract.h_wire | uint512(0x0) 674 | exchange_timestamp | contract.wire_deadline 675 | contract.refund_deadline 676 | sum(*deposit.fraction - *denom.fee_deposit) 677 | SHA-512(*deposit.sig1) | merchant.pub )) 678 ]]></artwork></figure> 679 680 </section> 681 </section> 682 <section anchor="security-considerations"><name>Security Considerations</name> 683 684 <t>[ TBD ]</t> 685 686 </section> 687 <section anchor="iana-considerations"><name>IANA Considerations</name> 688 689 <t>None.</t> 690 691 </section> 692 693 694 </middle> 695 696 <back> 697 698 699 <references title='Normative References' anchor="sec-normative-references"> 700 701 702 703 <reference anchor="RFC20"> 704 <front> 705 <title>ASCII format for network interchange</title> 706 <author fullname="V.G. Cerf" initials="V.G." surname="Cerf"/> 707 <date month="October" year="1969"/> 708 </front> 709 <seriesInfo name="STD" value="80"/> 710 <seriesInfo name="RFC" value="20"/> 711 <seriesInfo name="DOI" value="10.17487/RFC0020"/> 712 </reference> 713 714 <reference anchor="RFC2104"> 715 <front> 716 <title>HMAC: Keyed-Hashing for Message Authentication</title> 717 <author fullname="H. Krawczyk" initials="H." surname="Krawczyk"/> 718 <author fullname="M. Bellare" initials="M." surname="Bellare"/> 719 <author fullname="R. Canetti" initials="R." surname="Canetti"/> 720 <date month="February" year="1997"/> 721 <abstract> 722 <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> 723 </abstract> 724 </front> 725 <seriesInfo name="RFC" value="2104"/> 726 <seriesInfo name="DOI" value="10.17487/RFC2104"/> 727 </reference> 728 729 <reference anchor="RFC5869"> 730 <front> 731 <title>HMAC-based Extract-and-Expand Key Derivation Function (HKDF)</title> 732 <author fullname="H. Krawczyk" initials="H." surname="Krawczyk"/> 733 <author fullname="P. Eronen" initials="P." surname="Eronen"/> 734 <date month="May" year="2010"/> 735 <abstract> 736 <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> 737 </abstract> 738 </front> 739 <seriesInfo name="RFC" value="5869"/> 740 <seriesInfo name="DOI" value="10.17487/RFC5869"/> 741 </reference> 742 743 <reference anchor="RFC6234"> 744 <front> 745 <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title> 746 <author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake 3rd"/> 747 <author fullname="T. Hansen" initials="T." surname="Hansen"/> 748 <date month="May" year="2011"/> 749 <abstract> 750 <t>Federal Information Processing Standard, FIPS</t> 751 </abstract> 752 </front> 753 <seriesInfo name="RFC" value="6234"/> 754 <seriesInfo name="DOI" value="10.17487/RFC6234"/> 755 </reference> 756 757 <reference anchor="HKDF"> 758 <front> 759 <title>Cryptographic Extraction and Key Derivation: The HKDF Scheme</title> 760 <author fullname="Hugo Krawczyk" initials="H." surname="Krawczyk"> 761 <organization/> 762 </author> 763 <date year="2010"/> 764 </front> 765 <seriesInfo name="Lecture Notes in Computer Science" value="pp. 631-648"/> 766 <seriesInfo name="DOI" value="10.1007/978-3-642-14623-7_34"/> 767 <seriesInfo name="ISBN" value="["9783642146220", "9783642146237"]"/> 768 <refcontent>Springer Berlin Heidelberg</refcontent></reference> 769 770 <reference anchor="SHS"> 771 <front> 772 <title>Secure hash standard</title> 773 <author> 774 <organization/> 775 </author> 776 <date year="2015"/> 777 </front> 778 <seriesInfo name="DOI" value="10.6028/nist.fips.180-4"/> 779 <refcontent>National Institute of Standards and Technology (U.S.)</refcontent></reference> 780 781 782 783 784 </references> 785 786 787 788 <?line 651?> 789 790 <section anchor="change-log"><name>Change log</name> 791 792 </section> 793 <section numbered="false" anchor="acknowledgments"><name>Acknowledgments</name> 794 795 <t>[ TBD ]</t> 796 797 <t>This work was supported in part by the German Federal Ministry of 798 Education and Research (BMBF) within the project Concrete Contracts.</t> 799 800 </section> 801 802 803 </back> 804 805 <!-- ##markdown-source: 806 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 935 936 --> 937 938 </rfc> 939