lsd0013

LSD0013: The donau:// scheme
Log | Files | Refs

draft-grothoff-donau-00.xml (33974B)


      1 <?xml version="1.0" encoding="US-ASCII"?>
      2 <!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
      3 <!ENTITY RFC2119 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
      4 <!ENTITY RFC3986 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3986.xml">
      5 <!ENTITY RFC8174 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8174.xml">
      6 <!ENTITY RFC5234 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5234.xml">
      7 <!ENTITY RFC6234 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6234.xml">
      8 <!ENTITY RFC8032 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8032.xml">
      9 <!ENTITY RFC4648 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4648.xml">
     10 <!ENTITY RFC9498 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.9498.xml">
     11 <!ENTITY RFC8905 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8905.xml">
     12 ]>
     13 <?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
     14 <!-- SEE ALSO: https://docs.taler.net/core/taler-uri.html -->
     15 <?rfc strict="yes" ?>
     16 <?rfc toc="yes" ?>
     17 <?rfc symrefs="yes"?>
     18 <?rfc sortrefs="yes" ?>
     19 <?rfc compact="yes" ?>
     20 <?rfc subcompact="no" ?>
     21 
     22 <rfc category="info"
     23      docName="draft-grothoff-donau-00"
     24      ipr="trust200902">
     25 <!-- FIXME ipr is copied from lsd0001, need to be updated -->
     26   <front>
     27     <title abbrev="The 'donau' URI scheme">
     28       The 'donau' URI scheme for validation of Donau donation statements.
     29     </title>
     30 
     31     <author fullname="Christian Grothoff" initials="C.G." surname="Grothoff">
     32       <organization>Bern University of Applied Sciences</organization>
     33       <address>
     34         <postal>
     35           <street>H&ouml;heweg 80</street>
     36           <street></street>
     37           <city>Biel/Bienne</city>
     38 	      <code>CH-2501</code>
     39           <country>CH</country>
     40         </postal>
     41         <email>christian.grothoff@bfh.ch</email>
     42       </address>
     43     </author>
     44 
     45     <author fullname="Emmanuel Benoist" initials="E.B." surname="Benoist">
     46       <organization>Bern University of Applied Sciences</organization>
     47       <address>
     48         <postal>
     49           <street>H&ouml;heweg 80</street>
     50           <street></street>
     51           <city>Biel/Bienne</city>
     52 	      <code>CH-2501</code>
     53           <country>CH</country>
     54         </postal>
     55        <email>emmanuel.benoist@bfh.ch</email>
     56       </address>
     57     </author>
     58 
     59     
     60     <author fullname="Bohdan Potuzhnyi" initials="B.P." surname="Potuzhnyi">
     61       <organization>Bern University of Applied Sciences</organization>
     62       <address>
     63         <postal>
     64           <street>H&ouml;heweg 80</street>
     65           <street></street>
     66           <city>Biel/Bienne</city>
     67 	      <code>CH-2501</code>
     68           <country>CH</country>
     69         </postal>
     70         <email>bohdan.potuzhnyi@bfh.ch</email>
     71       </address>
     72     </author>
     73 
     74         
     75     <author fullname="Florian Dold" initials="F.D." surname="Dold">
     76       <organization>Taler Systems AG</organization>
     77       <address>
     78         <postal>
     79           <street>7, rue de Mondorf</street>
     80           <street></street>
     81           <city>Erpeldange</city>
     82 	      <code>L-5421</code>
     83           <country>Luxembourg</country>
     84         </postal>
     85         <email>dold@taler.net</email>
     86       </address>
     87     </author>
     88 
     89     
     90     <date day="17" month="October" year="2025" />
     91 
     92     <!-- Meta-data Declarations -->
     93     <area>General</area>
     94     <workgroup>Independent Stream</workgroup>
     95     <keyword>taxation</keyword>
     96 
     97     <abstract>
     98 
     99       <t>
    100         This document defines the 'donau' Uniform Resource Identifier (URI) scheme
    101         for triggering interactions with a validator for Donau donation
    102 	statements.
    103       </t>
    104 
    105       <t>
    106         This URI scheme allows applications to trigger interactions
    107         with a Donau validator.  A Donau validator is typically run by
    108         a tax authority to validate tax records from citizens that
    109         made donations to a charity that supports the Donau protocol.
    110         The Donau validator will receive 'donau' URIs representing the
    111         sum of donations a taxpayer made to recognized charities over
    112         a year.  Donors would submit 'donau' URLs (or QR codes with
    113         'donau' URLs) to tax authorities to have their donations
    114         recognized by the tax authority as tax-deductable
    115         expenditures.  The application logic to verify the validity of
    116         the donation is triggered by 'donau' URIs. The validator
    117         application would then typically confirm to the tax official
    118         the validity of the signature encoded in the URI and show the
    119         total amount donated as well as the taxpayer identification
    120         number and the year of the donation.  Multiple URIs could be
    121         submitted per donor, and the application can correctly
    122         determine which submissions are cummulative and which ones are
    123         redundant.
    124       </t>
    125 
    126       <t>
    127 	This specification only covers the syntax of the 'donau' URI
    128 	scheme and excludes details on the protocol(s) that would
    129 	allow taxpayers to donate to recognized charities to obtain
    130 	these suitable signed donation statements.  While a
    131 	privacy-preserving protocol to obtain such statements exists
    132 	within the context of the GNU Taler protocol suite, other
    133 	protocols could be developed in the future and still yield
    134 	compatible 'donau' URIs as the URI scheme is reasonably generic.
    135       </t>
    136 
    137     </abstract>
    138 
    139   </front>
    140 
    141   <middle>
    142 
    143 <section anchor="introduction" title="Introduction">
    144 <t>
    145   This document defines the 'donau' Uniform Resource Identifier (URI) <xref target="RFC3986" /> scheme
    146   for triggering interactions with Donau validators.
    147 </t>
    148 
    149 <section title="Objective">
    150 <t>
    151   A 'donau' URI always instructs a Donau validator to perform the
    152   validation of a Donau donation statement.
    153   A 'donau' URI consists of the reference to the authority
    154   that signed the statement, an identifier for the specific taxpayer,
    155   the year of the donation, a salt and optional parameters.
    156   Optional parameters include the amount donated by the
    157   taxpayer and the signature of the Donau donation statement.
    158 </t>
    159 </section>
    160 <section title="Requirements Language">
    161 <t>
    162    The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
    163    "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
    164    "OPTIONAL" in this document are to be interpreted as described in BCP 14
    165    <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when,
    166    they appear in all capitals, as shown here.
    167 </t>
    168 </section>
    169 
    170 </section>
    171 
    172 <section anchor="syntax"
    173   title="Syntax of a 'donau' URI">
    174   <t>
    175   This document uses the Augmented Backus-Naur Form (ABNF) of <xref target="RFC5234"/>.
    176   </t>
    177   <figure>
    178   <artwork type="abnf"><![CDATA[
    179   ; Scheme and high-level structure
    180   scheme    = "donau://" / "DONAU://" / "donau+http://" / "DONAU+HTTP://"
    181   donau-URI = scheme base "/" year "/" taxid-enc "/" salt
    182               [ "?" [ "total=" amount "&sig=" algo ":" signature ] ]
    183 
    184   ; The base is the HTTP(S) origin plus optional path segments that
    185   ; identify the Donau REST API deployment. Everything before the last
    186   ; three path segments (year, taxid-enc, salt) is part of the base.
    187   base      = 1*( ALPHA / DIGIT / "-" / "." / ":" / "/" / "_" )
    188 
    189   ; Path parameters
    190   year      = DIGIT DIGIT DIGIT DIGIT
    191 
    192   ; The taxid-enc is the percent-encoding (RFC 3986) of the UTF-8
    193   ; taxpayer identifier string. See semantics for decoding rules.
    194   taxid-enc = 1*( unreserved / pct-encoded )
    195   pct-encoded = "%" HEXDIG HEXDIG
    196   unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
    197 
    198   ; Salt remains an opaque string for the URI and is interpreted by
    199   ; the Donau system. (See semantics.)
    200   salt      = 1*( DIGIT )
    201 
    202   ; Query parameters and signature encoding
    203   amount    = currency ":" unit [ "." fraction ]
    204   currency  = 1*ALPHA
    205   unit      = 1*( DIGIT )
    206   fraction  = 1*( DIGIT )
    207   algo      = "ED25519"
    208   signature = *( ALPHA / DIGIT )
    209 ]]>
    210   </artwork>
    211   </figure>
    212 </section>
    213 
    214 <section anchor="semantics" title="Semantics">
    215   <t>
    216     The base of a Donau URI refers to the base URL of the Donau REST API.
    217     It consists of the network location (host name or IP address) and MAY include
    218     additional path segments (for example, <tt>https://admin.ch/taxes/donau/</tt>)
    219     mapping to the Donau deployment behind reverse proxies. Validators MUST NOT
    220     assume a specific domain naming scheme (such as <tt>donau.example</tt>) and
    221     MUST accept bases with or without additional path components.
    222   </t>
    223     <t>
    224     The year of a Donau URI referes to the year when the donations
    225     have been done.
    226     </t>
    227     <t>
    228     The taxid of a Donau URI referes to the taxid of the person that
    229     did the donations and asks for their Donau donation statement to
    230     be verified. The format of the taxid is specific for each tax authority.
    231     The taxid is conveyed in the URI as a single path segment using percent-encoding
    232     per <xref target="RFC3986"/>. Implementations MUST decode <tt>taxid-enc</tt>
    233     by applying percent-decoding to obtain the exact UTF-8 bytes of the tax identifier
    234     before any processing. In particular, the character '/' MUST be percent-encoded
    235     as <tt>%2F</tt> if present in a tax identifier.
    236     </t>
    237     <t>
    238     The salt of a Donau URI referes to the information used by the
    239     Donau-wallet application to generate the Donau donation statement. This salt is
    240     specific for each wallet, allowing a taxpayer to have many Donau
    241     donation statements for the same year that should be treated as
    242     cummulative by the validator application.  The salt can also be
    243     used to obfuscate the taxpayer ID in the donation protocol.
    244     </t>
    245     <t>
    246     The total follows the syntax from <xref target="RFC8905"/> and
    247     represents the total amount donated in this year by the given
    248     taxpayer with the given salt. Thus, given multiple 'donau' URIs
    249     with the same salt, the maximum amount should be used, while
    250     the amounts from 'donau' URIs with different salts should be
    251     added.
    252     </t>
    253     <t>
    254     Parsing note: A Donau validator MUST parse a Donau URI by taking the last three
    255     path segments as <tt>{year}/{taxid-enc}/{salt}</tt>, and treat all preceding
    256     path segments (plus the authority) as the <tt>base</tt>. This ensures that bases
    257     with additional path components are unambiguous even when tax identifiers contain
    258     reserved characters that are percent-encoded.
    259     </t>
    260     <t>
    261     Finally, <tt>algo</tt> specifies the specific signature algorithm
    262     used; for now,
    263     only ED25519 (see <xref target="RFC8032" />) is supported.
    264     The signature using the specified algorithm must be
    265     made over the information above (see <xref target="signature"/>)
    266     and MUST be encoded using the Base 32 U Crockford encoding
    267     scheme <xref target="base32-U-crockford"/>.
    268     </t>
    269     <t>
    270     The default operation of applications that invoke a URI with the
    271     Donau scheme MUST be to launch a Donau validator (if
    272     available). If no Donau validator is available, an application
    273     SHOULD show a QR code with the content of the URI. If multiple
    274     Donau validators are registered, the user SHOULD be able to choose
    275     which application to launch. This allows users with multiple
    276     validators to choose which validator to perform the operation
    277     with.
    278     </t>
    279     <t>
    280     An application SHOULD allow dereferencing a "donau://" URI even
    281     if the action of that URI is not registered in the "Donau URI
    282     Actions" sub-registry.
    283     </t>
    284     <t>
    285     Donau-validators seeing a "<tt>donau://</tt>" URI MUST use HTTP over TLS when talking
    286     to the respective network service.
    287     Donau-validators seeing a "<tt>donau+http://</tt>" URI MUST use HTTP without TLS when talking
    288     to the respective network service.  Donau-validators SHOULD support
    289     "<tt>donau+http://</tt>"-URIs only when run in developer or debug mode.
    290     Validators would contact the base to obtain the public key
    291     used for the signature. The base origin SHOULD also be shown to the
    292     user to indicate which authority issued the proof of donation.
    293     Alternatively, specific validation apps MAY only accept 'donau'
    294     URLs from a specific set of hard-coded authorities and simply display
    295     an error message when given 'donau' URLs from other authorities.
    296   </t>
    297 </section>
    298 
    299         <section anchor="examples" title="Examples">
    300             <figure>
    301                 <artwork><![CDATA[
    302     ; Minimal example with a simple base and simple taxid
    303     donau://example.com/2025/7560001010000/1234?total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28
    304 
    305     ; Example with percent-encoded taxid containing '/'
    306     donau://donau.test.taler.net/2025/123%2F456%2F789/1234?total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
    307 
    308     ; Example with a base URL that includes path components
    309     donau://admin.ch/taxes/donau/2025/7560001010000/1234?total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28
    310 ]]>
    311   </artwork>
    312 </figure>
    313 
    314 </section>
    315 
    316 <section anchor="verification" title="Verification of a Donau URI">
    317   <t>
    318   The verification requires the Donau verification application to test
    319   if a given taxpayer has got the right to be granted a tax
    320   reduction. For doing this, the Donau verification application must
    321   verify that the Donau-URI corresponds to a valid Donau donation
    322   statement. The Donau verification application MUST verify the
    323   validity of the donation statement. There are two possibilities:
    324   signature and total are available, or at least one is not available.
    325   </t>
    326   <t>
    327   If signature and total are available, then the verification
    328   application will verify
    329   that the signature is valid for the server key (see <xref
    330   target="get-server-keys"/> to get the key).
    331   </t>
    332   <t>
    333   If both are missing, the application MUST download them from
    334   the get donation statement endpoint <xref target="get-donation-statement"/>. 
    335   </t>
    336   
    337 </section>
    338 <section anchor="get-server-keys" title="Access the Donau server public
    339 					keys">
    340   <t>
    341     The verification app MUST have a signing public key
    342     corresponding to the base for the given year. The key MAY be retrieved from a
    343     cache. If no key for this base and this year is available in the
    344     cache, the verification app MUST download the key from the
    345     base. The Donau server MUST provide the key at the /keys
    346     entrypoint. If the key is not available, no verification can take place.
    347    
    348     The verification app SHOULD cache downloaded signing
    349     public keys for the current year. 
    350   </t>
    351   <t>
    352   
    353     <list style="symbols">
    354       <t>Endpoint: /keys</t>
    355       <t>Method: GET</t>
    356       <t>Syntax: base/keys</t>
    357       <t>Syntax response: defined hereunder</t>
    358       <t>Contact: N/A</t>
    359       <t>References: [this.I-D]</t>
    360     </list>
    361 
    362 
    363 
    364 
    365 
    366     Each of the "<tt>signkeys</tt>" is valid between "<tt>stamp_start</tt>" and
    367     "<tt>stamp_expire</tt>" and the public "<tt>key</tt>" returned is encoded using Base 32
    368     U Crockford encoding <xref target="base32-U-crockford"/>.
    369 
    370    <sourcecode>
    371         <![CDATA[
    372 ; Core JSON tokens (simplified; assumes standard JSON for strings, numbers, booleans, null, arrays, objects)
    373 JSONString      = DQUOTE *(%x20-21 / %x23-5B / %x5D-10FFFF / "\" EscapedChar) DQUOTE
    374 UCrockford = *( ALPHA32 / "-" )
    375 ALPHA32 = DIGIT / LETTER
    376 DIGIT   = %x30-39                       ; 0-9
    377 LETTER  = %x41-48 / %x4A-4E / %x50-5A / %x61-68 / %x6A-6E / %x70-7A
    378 JSONUCrockfordString      = DQUOTE UCrockford DQUOTE
    379 EscapedChar    = %x22 / %x5C / %x2F / %x62 / %x66 / %x6E / %x72 / %x74 / 
    380                  "u" 4HEXDIG
    381 JSONNumber     = [ "-" ] 1DIGIT *( DIGIT ) [ "." 1DIGIT *( DIGIT ) ] 
    382                  [ ( "e" / "E" ) [ "+" / "-" ] 1DIGIT *( DIGIT ) ]
    383 JSONBool       = "true" / "false"
    384 JSONNull       = "null"
    385 JSONArray      = "[" [ JSONException *( "," JSONException ) ] "]"
    386 JSONObject     = "{" [ JSONMember *( "," JSONMember ) ] "}"
    387 JSONMember     = JSONString ":" JSONException
    388 JSONException  = JSONString / JSONNumber / JSONObject / JSONArray / JSONBool / JSONNull
    389 
    390 ; Specific DonauKeysResponse structure
    391 DonauKeysResponse = "{" 
    392                       JSONMemberSep 
    393                     "}"
    394 JSONMemberSep  = version , domain , base_url , currency , currency_fraction_digits ,
    395                  donation_units , signkeys
    396 
    397 version       = DQUOTE "version" DQUOTE ":" JSONString
    398 domain        = DQUOTE "domain"  DQUOTE ":" JSONString
    399 base_url      = DQUOTE "base_url" DQUOTE ":" JSONString
    400 currency      = DQUOTE "currency" DQUOTE ":" JSONString
    401 currency_fraction_digits = DQUOTE "currency_fraction_digits" DQUOTE ":" JSONNumber
    402 EDDSAPubKey   = JSONUCrockfordString
    403 SignKey       = DQUOTE "key" DQUOTE ":" EDDSAPubKey
    404 donation_units = DQUOTE "donation_units" DQUOTE ":" "[" DonationUnitKeyGroup *( "," DonationUnitKeyGroup ) "]"
    405 signkeys       = DQUOTE "signkeys" DQUOTE ":" "[" SignKey *( "," SignKey ) "]"
    406 
    407 DonationUnitKeyGroup = "{" cipher_field "," value_field "," donation_units_array "}"
    408 cipher_field           = DQUOTE "cipher" DQUOTE ":" ( DQUOTE "RSA" DQUOTE / DQUOTE "CS" DQUOTE )
    409 value_field            = DQUOTE "value"  DQUOTE ":" JSONNumber
    410 donation_units_array   = DQUOTE "donation_units" DQUOTE ":" "[" DUNK_UNIT_KEY *( "," DUNK_UNIT_KEY ) "]"
    411 
    412 ; donation unit entries differ depending on cipher
    413 DUNK_UNIT_KEY = "{" base_fields "," key_specific "}"
    414 base_fields   = DQUOTE "year"  DQUOTE ":" JSONNumber [ "," DQUOTE "lost" DQUOTE ":" JSONBool ]
    415 key_specific  = ( DQUOTE "rsa_pub" DQUOTE ":" JSONObject ) / 
    416                 ( DQUOTE "cs_pub"  DQUOTE ":" JSONString )
    417 
    418 SignKey = "{" DQUOTE "key" DQUOTE ":" JSONObject "," DQUOTE "year" DQUOTE ":" JSONNumber "}"
    419         ]]>
    420       </sourcecode>
    421 
    422 Example, a response to a GET request to the <tt>/key/</tt> endpoint.
    423    <sourcecode>
    424         <![CDATA[
    425  {"signkeys":
    426    [ "stamp_start":{"ts_s":42},
    427      "stamp_expire":{"ts_s":43},
    428      "key":"XXXXXXXXXXXXXXXX"
    429    ]
    430  }
    431         ]]>
    432       </sourcecode>
    433       
    434 
    435   </t>
    436 </section>
    437 
    438 <section anchor="get-donation-statement" title="Get donation statement
    439 						and signature">
    440   <t>
    441     If the Donau-URI does not contain the total or the signature, the
    442     verification app MUST download them from the <tt>/donation-statement/</tt>
    443     endpoint of the base.<br/>
    444 
    445     The verification app will compute the donor hash H using SHA-512 <xref target="RFC6234"/>
    446     over the exact UTF-8 bytes of the taxpayer ID string, followed by a single
    447     NUL byte (0x00), followed by the salt string, followed by a final NUL byte (0x00):
    448     <tt>H = SHA-512(taxid || 0x00 || salt || 0x00)</tt>. Here, <tt>taxid</tt> is the
    449     UTF-8 string obtained by percent-decoding the <tt>taxid-enc</tt> path segment.
    450     This produces the <tt>hash-donor-id</tt>. The verification app will contact the
    451     base in the endpoint <tt>/donation-statement</tt> with the year and the hash-donor-id. 
    452 
    453     The <tt>hash-donor-id</tt> must be encoded using Base 32 U Crockford
    454     encoding <xref target="base32-U-crockford"/>.
    455 
    456     
    457     <list style="symbols">
    458       <t>Endpoint: /donation-statement</t>
    459       <t>Method: GET</t>
    460 <t>Syntax: base/donation-statement/{year}/{hash-donor-id}</t>
    461 <t>Contact: N/A</t>
    462 <t>References: [this.I-D]</t>
    463 </list>
    464 
    465 
    466 Servers implementing the donation-statement endpoint MUST respect the
    467 following syntax; all three fields (<tt>total-field</tt>, <tt>sig-field</tt>, <tt>pub-field</tt>) MUST be included.
    468 
    469 The amount is a string formed first of the currency (in capital
    470 letters) then ":" and then the value (can be an integer or a decimal
    471 number).
    472 
    473    <sourcecode>
    474         <![CDATA[
    475 json-object     = "{" ws field-list ws "}"
    476 
    477 field-list      = field *(ws "," ws field)
    478 field           = total-field / sig-field / pub-field
    479 
    480 ; Allow any order of the three fields
    481 total-field     = DQUOTE "total" DQUOTE ws ":" ws DQUOTE currency ":" value DQUOTE
    482 sig-field       = DQUOTE "donation_statement_sig" DQUOTE ws ":" ws DQUOTE signature DQUOTE
    483 pub-field       = DQUOTE "donau_pub" DQUOTE ws ":" ws DQUOTE signature DQUOTE  ; same format as signature
    484 
    485 currency        = 1*(%x41-5A)   ; A-Z uppercase letters
    486 value           = int / decimal
    487 int             = ["-"] 1*DIGIT
    488 decimal         = ["-"] 1*DIGIT "." 1*DIGIT
    489 
    490 signature       = 1*(ALPHA / DIGIT / "=")
    491 
    492 ; Common tokens
    493 ws              = *WSP
    494 DQUOTE          = %x22  ; "
    495 WSP             = %x20 / %x09
    496 DIGIT           = %x30-39
    497 ALPHA           = %x41-5A / %x61-7A
    498         ]]>
    499       </sourcecode>
    500 
    501       
    502 
    503 Example of an element of USD 100.00 :
    504    <sourcecode>
    505         <![CDATA[
    506 {
    507    total: "USD:100",
    508    donation_statement_sig: "SIGNATURE",
    509    donau_pub: "EDDSA_PUBLIC_KEY"
    510 }
    511         ]]>
    512       </sourcecode>
    513 
    514 
    515   </t>
    516 </section>
    517 <section anchor="signature-total-available" title="Signature and
    518 						    total are available">
    519   <t>
    520     The verification app MUST verify that the signature corresponds to
    521     the claimed values.
    522 
    523     If the information is not in the URI, the verification app MUST download the total and the signature from the
    524     base using the GET /donation-statement/ endpoint <xref
    525     target="get-donation-statement"/>. Otherwise, it SHOULD use the
    526     value given in the URI. 
    527 
    528     The verification of the signature is done using EdDSA as
    529     specified in <xref target="RFC8032" />.
    530 
    531     The verification MAY be done with the following instructions. The signed data is the concatenation of the following fields in network byte order (big-endian):
    532 
    533     <ul>
    534       <li>size (4 bytes): 32-bit unsigned integer with the total length of the signed data in bytes.</li>
    535       <li>purpose (4 bytes): 32-bit unsigned integer with the constant value <tt>1500</tt>.</li>
    536       <li>total value (8 bytes): integer part as an unsigned 64-bit integer.</li>
    537       <li>total fraction (4 bytes): fractional part as an unsigned 32-bit integer in units of 1/100000000.</li>
    538       <li>currency (12 bytes): ASCII, left-aligned and zero-padded to 12 bytes.</li>
    539       <li>donor hash H (64 bytes): <tt>H = SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>.</li>
    540       <li>year (4 bytes): 32-bit unsigned integer (the donation year).</li>
    541     </ul>
    542     
    543 </t>
    544 </section>
    545 
    546 <section anchor="signature" title="Signature of the donation statement ">
    547   <t>
    548     The server signing the donation statement  <bcp14>MUST</bcp14> use the Sign(d,message) procedure implemented as defined in <xref target="RFC8032" />.
    549   </t>
    550   <figure anchor="figure_signature_data" title="The binary representation of the data to sign">
    551        <artwork name="" type="" align="left" alt=""><![CDATA[
    552 0
    553 ]]></artwork>
    554      </figure>
    555 
    556 
    557 
    558      <t>
    559          The signature over the public key covers a 32-bit pseudo header
    560          conceptually prefixed to the EXPIRATION and BDATA fields.
    561          The wire format is illustrated
    562          in <xref target="figure_rrsigwithpseudo"/>.
    563         </t>
    564         <figure anchor="figure_rrsigwithpseudo">
    565           <name>The Wire Format Used for Creating the Signature of the RRBLOCK</name>
    566           <artwork name="" type="" alt="">
    567 0     8     16    24    32    40    48    56
    568 +-----+-----+-----+-----+-----+-----+-----+-----+
    569 |         SIZE          |       PURPOSE (1500)  |
    570 +-----+-----+-----+-----+-----+-----+-----+-----+
    571 |                TOTAL value                    |
    572 +-----+-----+-----+-----+-----+-----+-----+-----+
    573 |       TOTAL  fraction |     CURRENCY          |
    574 +-----+-----+-----+-----+                       +
    575 |                                               |
    576 +-----+-----+-----+-----+-----+-----+-----+-----+
    577 |              SHA512 of the donor ID           |
    578 /                                               /
    579 /                                               /
    580 +-----+-----+-----+-----+-----+-----+-----+-----+
    581 |       YEAR            |
    582 +-----+-----+-----+-----+
    583            </artwork>
    584         </figure>
    585         <dl newline="false">
    586           <dt>SIZE:</dt>
    587           <dd>
    588            A 32-bit value containing the length of the signed data in bytes
    589            in network byte order.
    590          </dd>
    591           <dt>PURPOSE:</dt>
    592           <dd>
    593            A 32-bit signature purpose flag in network byte order. The value of this
    594            field <bcp14>MUST</bcp14> be 1500.  It defines the context in which
    595            the signature is created so that it cannot be reused in other parts
    596            of the protocol that might include possible future extensions.
    597            The value of this field corresponds to an entry in the
    598            GANA "GNUnet Signature Purposes" registry <xref target="GANA"/>.
    599          </dd>
    600           <dt>TOTAL value:</dt>
    601           <dd>
    602             The integer part of the total value. Unsigned integer containing the integer part of the value for the total. It is represented on 64 bits value (in big endian),
    603          </dd>
    604           <dt>TOTAL fraction:</dt>
    605           <dd>
    606 	    The fractional part of the total value is represented by an unsigned integer on 32 bits (also in big endian notation). It represents the fractional part of the value  in 1/100000000th of the base unit.
    607 	  </dd>
    608           <dt>TOTAL currency</dt>
    609           <dd>
    610             A string representing the currency. ASCII, left-aligned and zero-padded to exactly 12 bytes.
    611          </dd>
    612           <dt>HASH:</dt>
    613           <dd>The SHA512 hash code for the donor ID.</dd>
    614           <dt>YEAR:</dt>
    615           <dd>The year on a 32 bit unsigned integer in big endian.</dd>
    616         </dl>
    617        </section>
    618 
    619 <section anchor="signature-verification" title="Signature verification for a donation statement">
    620   <t>
    621 The signature verification step is taking the data presented in the figure <xref target="figure_signature_data" /> as
    622 input. Signature MUST be verified using the EdDSA scheme described in
    623 <xref target="RFC8032" /> the procedure is Verify(zk,message,signature). Public key and signature are given
    624 encoded in Base 32 U Crockford MUST first be decoded to get a binary
    625 out of it.
    626   </t>
    627   <t>
    628            The Sign(d,message) and Verify(zk,message,signature) procedures <bcp14>MUST</bcp14>
    629            be implemented as defined in <xref target="RFC8032" />.
    630          </t>
    631      
    632 </section>
    633 
    634 <section anchor="base32-U-crockford" title="Base 32 representation of
    635 					    binary data">
    636 <t>All binary data MUST be encoded to be transmitted. For encoding, one
    637 MUST use the Base32 U Crockford encoding. This is a variation of the
    638 base32 encoding <xref target ="RFC4648" />. This encoding is presented
    639 in details in the appendix of the RFC for GNU Name System <xref target="RFC9498" />
    640 </t>
    641 <t>
    642 The encoding works similarly to the standard, but uses another Base 32
    643 Alphabet. The new alphabet is given in the Table <xref target="figure_base32_encoding" />, below.
    644 </t>
    645 
    646 <figure anchor="figure_base32_encoding" title="The Base 32 Encoding Alphabet.">
    647   <artwork name="" type="" align="left" alt="table where value beween 0 and 9 are encoded with the character corresponding to the number. Then between 10 and 31, we have all the letters expect I, L, O, U that could be missleading (OCR may not recognize them properly). Pading is the char ="><![CDATA[
    648 Value Encoding  Value Encoding  Value Encoding  Value Encoding
    649     0 0             9 9            18 J            27 V
    650     1 1            10 A            19 K            28 W
    651     2 2            11 B            20 M            29 X
    652     3 3            12 C            21 N            30 Y
    653     4 4            13 D            22 P            31 Z
    654     5 5            14 E            23 Q
    655     6 6            15 F            24 R           (pad) =
    656     7 7            16 G            25 S
    657     8 8            17 H            26 T
    658 
    659     ]]>
    660   </artwork>
    661 </figure>
    662 	 
    663 <t>	 
    664 To prevent optical character reading (OCR) problems, a system decoding binary data encoded with base 32 U Crockford MUST
    665 accept the codes presented in the Table <xref target="figure_base32_decoding"/>, below. System reading a U
    666 MUST evaluate it as a V. 
    667 </t>
    668 
    669   <figure anchor="figure_base32_decoding" title="The Base 32 Decoding Alphabet.">
    670         <artwork name="" type="" align="left" alt=""><![CDATA[
    671 Value Encoding  Value Encoding  Value Encoding  Value Encoding
    672     0 0             9 9            18 J|j          27 V|v|u|U
    673     1 1|i|I|l|L    10 A|a          19 K|k          28 W|w
    674     2 2            11 B|b          20 M|m          29 X|x
    675     3 3            12 C|c          21 N|n          30 Y|y
    676     4 4            13 D|d          22 P|p          31 Z|z
    677     5 5            14 E|e          23 Q|q
    678     6 6            15 F|f          24 R|r        (pad) =
    679     7 7            16 G|g          25 S|s
    680     8 8            17 H|h          26 T|t
    681     ]]></artwork>
    682       </figure>
    683 	 
    684 
    685 
    686         </section>
    687 
    688         <section anchor="appendix-test-vectors" title="Appendix. Test Vector: Verify from URI">
    689             <t>
    690                 This appendix shows how to verify a donation statement starting from a
    691                 received URI. Public key is fetched from the Donau base.
    692             </t>
    693 
    694             <figure>
    695                 <artwork><![CDATA[
    696 Example URI:
    697 donau://donau.test.taler.net/2025/123%2F456%2F789/AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0?total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
    698 
    699 Extracted fields:
    700 - base: donau.test.taler.net
    701 - year: 2025
    702 - taxid: 123%2F456%2F789
    703 - taxid (decoded): 123/456/789
    704 - salt: AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0
    705 - total: TESTKUDOS:1
    706 - signature: ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
    707 
    708 Fetched public key for year 2025 from https://donau.test.taler.net/keys:
    709 - pub: 2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG
    710         ]]></artwork>
    711             </figure>
    712 
    713       <t>Verification steps:</t>
    714       <list style="numbers">
    715         <t>Input (URI):<br/>
    716 <tt>donau://donau.test.taler.net/2025/123%2F456%2F789/AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0?total=TESTKUDOS:1&amp;sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30</tt></t>
    717         <t>Parse fields:<br/>
    718           - base: <tt>donau.test.taler.net</tt><br/>
    719           - year: <tt>2025</tt> (4 digits)<br/>
    720           - taxid-enc: <tt>123%2F456%2F789</tt><br/>
    721           - taxid (UTF-8, percent-decoded, no trimming): <tt>123/456/789</tt><br/>
    722           - salt (ASCII): <tt>AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0</tt><br/>
    723           - total (amount string): <tt>TESTKUDOS:1</tt><br/>
    724           - sig (Crockford Base32, algorithm ED25519): <tt>B14WGS...XGY30</tt></t>
    725         <t>Public signing key (Crockford Base32) (from <tt>/keys</tt>):<br/>
    726 <tt>2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG</tt></t>
    727         <t>Donor hash <tt>H</tt> = <tt>SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>:<br/>
    728           - length: 64 bytes<br/>
    729           - hex:<br/>
    730 <tt>4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b</tt><br/>
    731           - Crockford Base32 (for HTTP endpoints):<br/>
    732 <tt>9AN1W5QWBFJ4GGNRCERZ2ZD3JABCMYSN56KJ1R8TQAE8QNS9YYGY5ERBK8WW0B973PJXT5DEMSPEJPZ7HF5F706Y36GBVF6RMY9RY6R</tt></t>
    733         <t>Amount encoding (<tt>TALER_AmountNBO</tt>):<br/>
    734           - currency (12 bytes): <tt>"TESTKUDOS"</tt> then <tt>0x00</tt> x 3<br/>
    735           - value (uint64 BE): <tt>1</tt> -> <tt>0x0000000000000001</tt><br/>
    736           - fraction (uint32 BE): <tt>0</tt> -> <tt>0x00000000</tt></t>
    737         <t>Signed message <tt>M</tt> layout (network byte order, total 100 bytes):<br/>
    738           - [0000..0003] 4 bytes <tt>size</tt>: <tt>0x00000064</tt><br/>
    739           - [0004..0007] 4 bytes <tt>purpose</tt>: <tt>0x000005DC</tt> (1500)<br/>
    740           - [0008..0015] 8 bytes <tt>amount.value</tt>: <tt>0x0000000000000001</tt><br/>
    741           - [0016..0019] 4 bytes <tt>amount.fraction</tt>: <tt>0x00000000</tt><br/>
    742           - [0020..0031] 12 bytes <tt>amount.currency</tt>: <tt>54 45 53 54 4b 55 44 4f 53 00 00 00</tt> ("TESTKUDOS\x00\x00\x00")<br/>
    743           - [0032..0095] 64 bytes <tt>i.hash</tt>: donor hash <tt>H</tt><br/>
    744           - [0096..0099] 4 bytes <tt>year</tt>: <tt>0x000007E9</tt> (2025)</t>
    745         <t>Message <tt>M</tt> (hex, 100 bytes):<br/>
    746 <tt>00000064 000005dc 0000000000000001 00000000 544553544b55444f53000000 4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b 000007e9</tt></t>
    747         <t>Signature (ED25519, Crockford Base32 -> bytes):<br/>
    748           - length: 64 bytes<br/>
    749           - R (first 32 bytes, hex):<br/>
    750 <tt>5849c864837bece5a254ce0dc0c51434e2956c6393e2339b06b5054ac490c088</tt><br/>
    751           - S (last 32 bytes, hex):<br/>
    752 <tt>fb05891b09fb36020f0bcf132acfee46632411de4e4bf27fe972f891fd7b0f0c</tt></t>
    753         <t>Public key (Ed25519, Crockford Base32 -> bytes):<br/>
    754           - length: 32 bytes<br/>
    755           - hex:<br/>
    756 <tt>13f15131534b68de38253f0d1f24f856f3607d8c6011d4d4d268a9339023ef7f</tt></t>
    757         <t>Verification (expected): call <tt>crypto_sign_verify_detached(sig, M, 100, pubkey)</tt>. The result MUST indicate a valid signature for this vector.</t>
    758         <t>Negative check (optional): flip one bit of <tt>M</tt> or <tt>sig</tt> and repeat; verification MUST fail.</t>
    759       </list>
    760     </section>
    761 
    762 
    763 
    764 
    765 
    766 </middle>
    767 
    768 <back>
    769 
    770   <references title="Normative References">
    771 
    772     &RFC2119;
    773 
    774     &RFC3986;
    775 
    776     &RFC8174;
    777 
    778     &RFC5234;
    779 
    780     &RFC6234; 
    781 
    782     &RFC8032; 
    783 
    784     &RFC9498; 
    785 
    786     &RFC8905; 
    787 
    788 
    789   </references>
    790 
    791   <references title="Informational References">
    792 
    793     &RFC4648; 
    794 
    795 
    796  <reference anchor="GANA" target="https://gana.gnunet.org/">
    797    <front>
    798        <title>GNUnet Assigned Numbers Authority (GANA)</title>
    799       <author><organization>GNUnet e.V.</organization>
    800       </author>
    801        <date month="April" year="2020" />
    802    </front>
    803  </reference>
    804 
    805   </references>
    806 
    807 <!-- Change Log
    808 v00 2022-11-11  CG   Initial version
    809   -->
    810 </back>
    811 </rfc>