<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY RFC2119 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC3986 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3986.xml">
<!ENTITY RFC8174 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8174.xml">
<!ENTITY RFC5234 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5234.xml">
<!ENTITY RFC6234 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6234.xml">
<!ENTITY RFC8032 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8032.xml">
<!ENTITY RFC4648 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4648.xml">
<!ENTITY RFC9498 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.9498.xml">
<!ENTITY RFC8905 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8905.xml">
]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<!-- SEE ALSO: https://docs.taler.net/core/taler-uri.html -->
<?rfc strict="yes" ?>
<?rfc toc="yes" ?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes" ?>
<?rfc compact="yes" ?>
<?rfc subcompact="no" ?>

<rfc category="info"
     docName="draft-grothoff-donau-00"
     ipr="trust200902">
<!-- FIXME ipr is copied from lsd0001, need to be updated -->
  <front>
    <title abbrev="The 'donau' URI scheme">
      The 'donau' URI scheme for validation of Donau donation statements.
    </title>

    <author fullname="Christian Grothoff" initials="C.G." surname="Grothoff">
      <organization>Bern University of Applied Sciences</organization>
      <address>
        <postal>
          <street>H&ouml;heweg 80</street>
          <street></street>
          <city>Biel/Bienne</city>
	      <code>CH-2501</code>
          <country>CH</country>
        </postal>
        <email>christian.grothoff@bfh.ch</email>
      </address>
    </author>

    <author fullname="Emmanuel Benoist" initials="E.B." surname="Benoist">
      <organization>Bern University of Applied Sciences</organization>
      <address>
        <postal>
          <street>H&ouml;heweg 80</street>
          <street></street>
          <city>Biel/Bienne</city>
	      <code>CH-2501</code>
          <country>CH</country>
        </postal>
       <email>emmanuel.benoist@bfh.ch</email>
      </address>
    </author>

    
    <author fullname="Bohdan Potuzhnyi" initials="B.P." surname="Potuzhnyi">
      <organization>Bern University of Applied Sciences</organization>
      <address>
        <postal>
          <street>H&ouml;heweg 80</street>
          <street></street>
          <city>Biel/Bienne</city>
	      <code>CH-2501</code>
          <country>CH</country>
        </postal>
        <email>bohdan.potuzhnyi@bfh.ch</email>
      </address>
    </author>

        
    <author fullname="Florian Dold" initials="F.D." surname="Dold">
      <organization>Taler Systems AG</organization>
      <address>
        <postal>
          <street>7, rue de Mondorf</street>
          <street></street>
          <city>Erpeldange</city>
	      <code>L-5421</code>
          <country>Luxembourg</country>
        </postal>
        <email>dold@taler.net</email>
      </address>
    </author>

    
    <date day="17" month="October" year="2025" />

    <!-- Meta-data Declarations -->
    <area>General</area>
    <workgroup>Independent Stream</workgroup>
    <keyword>taxation</keyword>

    <abstract>

      <t>
        This document defines the 'donau' Uniform Resource Identifier (URI) scheme
        for triggering interactions with a validator for Donau donation
	statements.
      </t>

      <t>
        This URI scheme allows applications to trigger interactions
        with a Donau validator.  A Donau validator is typically run by
        a tax authority to validate tax records from citizens that
        made donations to a charity that supports the Donau protocol.
        The Donau validator will receive 'donau' URIs representing the
        sum of donations a taxpayer made to recognized charities over
        a year.  Donors would submit 'donau' URLs (or QR codes with
        'donau' URLs) to tax authorities to have their donations
        recognized by the tax authority as tax-deductable
        expenditures.  The application logic to verify the validity of
        the donation is triggered by 'donau' URIs. The validator
        application would then typically confirm to the tax official
        the validity of the signature encoded in the URI and show the
        total amount donated as well as the taxpayer identification
        number and the year of the donation.  Multiple URIs could be
        submitted per donor, and the application can correctly
        determine which submissions are cummulative and which ones are
        redundant.
      </t>

      <t>
	This specification only covers the syntax of the 'donau' URI
	scheme and excludes details on the protocol(s) that would
	allow taxpayers to donate to recognized charities to obtain
	these suitable signed donation statements.  While a
	privacy-preserving protocol to obtain such statements exists
	within the context of the GNU Taler protocol suite, other
	protocols could be developed in the future and still yield
	compatible 'donau' URIs as the URI scheme is reasonably generic.
      </t>

    </abstract>

  </front>

  <middle>

<section anchor="introduction" title="Introduction">
<t>
  This document defines the 'donau' Uniform Resource Identifier (URI) <xref target="RFC3986" /> scheme
  for triggering interactions with Donau validators.
</t>

<section title="Objective">
<t>
  A 'donau' URI always instructs a Donau validator to perform the
  validation of a Donau donation statement.
  A 'donau' URI consists of the reference to the authority
  that signed the statement, an identifier for the specific taxpayer,
  the year of the donation, a salt and optional parameters.
  Optional parameters include the amount donated by the
  taxpayer and the signature of the Donau donation statement.
</t>
</section>
<section title="Requirements Language">
<t>
   The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in BCP 14
   <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when,
   they appear in all capitals, as shown here.
</t>
</section>

</section>

<section anchor="syntax"
  title="Syntax of a 'donau' URI">
  <t>
  This document uses the Augmented Backus-Naur Form (ABNF) of <xref target="RFC5234"/>.
  </t>
  <figure>
  <artwork type="abnf"><![CDATA[
  ; Scheme and high-level structure
  scheme    = "donau://" / "DONAU://" / "donau+http://" / "DONAU+HTTP://"
  donau-URI = scheme base "/" year "/" taxid-enc "/" salt
              [ "?" [ "total=" amount "&sig=" algo ":" signature ] ]

  ; The base is the HTTP(S) origin plus optional path segments that
  ; identify the Donau REST API deployment. Everything before the last
  ; three path segments (year, taxid-enc, salt) is part of the base.
  base      = 1*( ALPHA / DIGIT / "-" / "." / ":" / "/" / "_" )

  ; Path parameters
  year      = DIGIT DIGIT DIGIT DIGIT

  ; The taxid-enc is the percent-encoding (RFC 3986) of the UTF-8
  ; taxpayer identifier string. See semantics for decoding rules.
  taxid-enc = 1*( unreserved / pct-encoded )
  pct-encoded = "%" HEXDIG HEXDIG
  unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"

  ; Salt remains an opaque string for the URI and is interpreted by
  ; the Donau system. (See semantics.)
  salt      = 1*( DIGIT )

  ; Query parameters and signature encoding
  amount    = currency ":" unit [ "." fraction ]
  currency  = 1*ALPHA
  unit      = 1*( DIGIT )
  fraction  = 1*( DIGIT )
  algo      = "ED25519"
  signature = *( ALPHA / DIGIT )
]]>
  </artwork>
  </figure>
</section>

<section anchor="semantics" title="Semantics">
  <t>
    The base of a Donau URI refers to the base URL of the Donau REST API.
    It consists of the network location (host name or IP address) and MAY include
    additional path segments (for example, <tt>https://admin.ch/taxes/donau/</tt>)
    mapping to the Donau deployment behind reverse proxies. Validators MUST NOT
    assume a specific domain naming scheme (such as <tt>donau.example</tt>) and
    MUST accept bases with or without additional path components.
  </t>
    <t>
    The year of a Donau URI referes to the year when the donations
    have been done.
    </t>
    <t>
    The taxid of a Donau URI referes to the taxid of the person that
    did the donations and asks for their Donau donation statement to
    be verified. The format of the taxid is specific for each tax authority.
    The taxid is conveyed in the URI as a single path segment using percent-encoding
    per <xref target="RFC3986"/>. Implementations MUST decode <tt>taxid-enc</tt>
    by applying percent-decoding to obtain the exact UTF-8 bytes of the tax identifier
    before any processing. In particular, the character '/' MUST be percent-encoded
    as <tt>%2F</tt> if present in a tax identifier.
    </t>
    <t>
    The salt of a Donau URI referes to the information used by the
    Donau-wallet application to generate the Donau donation statement. This salt is
    specific for each wallet, allowing a taxpayer to have many Donau
    donation statements for the same year that should be treated as
    cummulative by the validator application.  The salt can also be
    used to obfuscate the taxpayer ID in the donation protocol.
    </t>
    <t>
    The total follows the syntax from <xref target="RFC8905"/> and
    represents the total amount donated in this year by the given
    taxpayer with the given salt. Thus, given multiple 'donau' URIs
    with the same salt, the maximum amount should be used, while
    the amounts from 'donau' URIs with different salts should be
    added.
    </t>
    <t>
    Parsing note: A Donau validator MUST parse a Donau URI by taking the last three
    path segments as <tt>{year}/{taxid-enc}/{salt}</tt>, and treat all preceding
    path segments (plus the authority) as the <tt>base</tt>. This ensures that bases
    with additional path components are unambiguous even when tax identifiers contain
    reserved characters that are percent-encoded.
    </t>
    <t>
    Finally, <tt>algo</tt> specifies the specific signature algorithm
    used; for now,
    only ED25519 (see <xref target="RFC8032" />) is supported.
    The signature using the specified algorithm must be
    made over the information above (see <xref target="signature"/>)
    and MUST be encoded using the Base 32 U Crockford encoding
    scheme <xref target="base32-U-crockford"/>.
    </t>
    <t>
    The default operation of applications that invoke a URI with the
    Donau scheme MUST be to launch a Donau validator (if
    available). If no Donau validator is available, an application
    SHOULD show a QR code with the content of the URI. If multiple
    Donau validators are registered, the user SHOULD be able to choose
    which application to launch. This allows users with multiple
    validators to choose which validator to perform the operation
    with.
    </t>
    <t>
    An application SHOULD allow dereferencing a "donau://" URI even
    if the action of that URI is not registered in the "Donau URI
    Actions" sub-registry.
    </t>
    <t>
    Donau-validators seeing a "<tt>donau://</tt>" URI MUST use HTTP over TLS when talking
    to the respective network service.
    Donau-validators seeing a "<tt>donau+http://</tt>" URI MUST use HTTP without TLS when talking
    to the respective network service.  Donau-validators SHOULD support
    "<tt>donau+http://</tt>"-URIs only when run in developer or debug mode.
    Validators would contact the base to obtain the public key
    used for the signature. The base origin SHOULD also be shown to the
    user to indicate which authority issued the proof of donation.
    Alternatively, specific validation apps MAY only accept 'donau'
    URLs from a specific set of hard-coded authorities and simply display
    an error message when given 'donau' URLs from other authorities.
  </t>
</section>

        <section anchor="examples" title="Examples">
            <figure>
                <artwork><![CDATA[
    ; Minimal example with a simple base and simple taxid
    donau://example.com/2025/7560001010000/1234?total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28

    ; Example with percent-encoded taxid containing '/'
    donau://donau.test.taler.net/2025/123%2F456%2F789/1234?total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30

    ; Example with a base URL that includes path components
    donau://admin.ch/taxes/donau/2025/7560001010000/1234?total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28
]]>
  </artwork>
</figure>

</section>

<section anchor="verification" title="Verification of a Donau URI">
  <t>
  The verification requires the Donau verification application to test
  if a given taxpayer has got the right to be granted a tax
  reduction. For doing this, the Donau verification application must
  verify that the Donau-URI corresponds to a valid Donau donation
  statement. The Donau verification application MUST verify the
  validity of the donation statement. There are two possibilities:
  signature and total are available, or at least one is not available.
  </t>
  <t>
  If signature and total are available, then the verification
  application will verify
  that the signature is valid for the server key (see <xref
  target="get-server-keys"/> to get the key).
  </t>
  <t>
  If both are missing, the application MUST download them from
  the get donation statement endpoint <xref target="get-donation-statement"/>. 
  </t>
  
</section>
<section anchor="get-server-keys" title="Access the Donau server public
					keys">
  <t>
    The verification app MUST have a signing public key
    corresponding to the base for the given year. The key MAY be retrieved from a
    cache. If no key for this base and this year is available in the
    cache, the verification app MUST download the key from the
    base. The Donau server MUST provide the key at the /keys
    entrypoint. If the key is not available, no verification can take place.
   
    The verification app SHOULD cache downloaded signing
    public keys for the current year. 
  </t>
  <t>
  
    <list style="symbols">
      <t>Endpoint: /keys</t>
      <t>Method: GET</t>
      <t>Syntax: base/keys</t>
      <t>Syntax response: defined hereunder</t>
      <t>Contact: N/A</t>
      <t>References: [this.I-D]</t>
    </list>





    Each of the "<tt>signkeys</tt>" is valid between "<tt>stamp_start</tt>" and
    "<tt>stamp_expire</tt>" and the public "<tt>key</tt>" returned is encoded using Base 32
    U Crockford encoding <xref target="base32-U-crockford"/>.

   <sourcecode>
        <![CDATA[
; Core JSON tokens (simplified; assumes standard JSON for strings, numbers, booleans, null, arrays, objects)
JSONString      = DQUOTE *(%x20-21 / %x23-5B / %x5D-10FFFF / "\" EscapedChar) DQUOTE
UCrockford = *( ALPHA32 / "-" )
ALPHA32 = DIGIT / LETTER
DIGIT   = %x30-39                       ; 0-9
LETTER  = %x41-48 / %x4A-4E / %x50-5A / %x61-68 / %x6A-6E / %x70-7A
JSONUCrockfordString      = DQUOTE UCrockford DQUOTE
EscapedChar    = %x22 / %x5C / %x2F / %x62 / %x66 / %x6E / %x72 / %x74 / 
                 "u" 4HEXDIG
JSONNumber     = [ "-" ] 1DIGIT *( DIGIT ) [ "." 1DIGIT *( DIGIT ) ] 
                 [ ( "e" / "E" ) [ "+" / "-" ] 1DIGIT *( DIGIT ) ]
JSONBool       = "true" / "false"
JSONNull       = "null"
JSONArray      = "[" [ JSONException *( "," JSONException ) ] "]"
JSONObject     = "{" [ JSONMember *( "," JSONMember ) ] "}"
JSONMember     = JSONString ":" JSONException
JSONException  = JSONString / JSONNumber / JSONObject / JSONArray / JSONBool / JSONNull

; Specific DonauKeysResponse structure
DonauKeysResponse = "{" 
                      JSONMemberSep 
                    "}"
JSONMemberSep  = version , domain , base_url , currency , currency_fraction_digits ,
                 donation_units , signkeys

version       = DQUOTE "version" DQUOTE ":" JSONString
domain        = DQUOTE "domain"  DQUOTE ":" JSONString
base_url      = DQUOTE "base_url" DQUOTE ":" JSONString
currency      = DQUOTE "currency" DQUOTE ":" JSONString
currency_fraction_digits = DQUOTE "currency_fraction_digits" DQUOTE ":" JSONNumber
EDDSAPubKey   = JSONUCrockfordString
SignKey       = DQUOTE "key" DQUOTE ":" EDDSAPubKey
donation_units = DQUOTE "donation_units" DQUOTE ":" "[" DonationUnitKeyGroup *( "," DonationUnitKeyGroup ) "]"
signkeys       = DQUOTE "signkeys" DQUOTE ":" "[" SignKey *( "," SignKey ) "]"

DonationUnitKeyGroup = "{" cipher_field "," value_field "," donation_units_array "}"
cipher_field           = DQUOTE "cipher" DQUOTE ":" ( DQUOTE "RSA" DQUOTE / DQUOTE "CS" DQUOTE )
value_field            = DQUOTE "value"  DQUOTE ":" JSONNumber
donation_units_array   = DQUOTE "donation_units" DQUOTE ":" "[" DUNK_UNIT_KEY *( "," DUNK_UNIT_KEY ) "]"

; donation unit entries differ depending on cipher
DUNK_UNIT_KEY = "{" base_fields "," key_specific "}"
base_fields   = DQUOTE "year"  DQUOTE ":" JSONNumber [ "," DQUOTE "lost" DQUOTE ":" JSONBool ]
key_specific  = ( DQUOTE "rsa_pub" DQUOTE ":" JSONObject ) / 
                ( DQUOTE "cs_pub"  DQUOTE ":" JSONString )

SignKey = "{" DQUOTE "key" DQUOTE ":" JSONObject "," DQUOTE "year" DQUOTE ":" JSONNumber "}"
        ]]>
      </sourcecode>

Example, a response to a GET request to the <tt>/key/</tt> endpoint.
   <sourcecode>
        <![CDATA[
 {"signkeys":
   [ "stamp_start":{"ts_s":42},
     "stamp_expire":{"ts_s":43},
     "key":"XXXXXXXXXXXXXXXX"
   ]
 }
        ]]>
      </sourcecode>
      

  </t>
</section>

<section anchor="get-donation-statement" title="Get donation statement
						and signature">
  <t>
    If the Donau-URI does not contain the total or the signature, the
    verification app MUST download them from the <tt>/donation-statement/</tt>
    endpoint of the base.<br/>

    The verification app will compute the donor hash H using SHA-512 <xref target="RFC6234"/>
    over the exact UTF-8 bytes of the taxpayer ID string, followed by a single
    NUL byte (0x00), followed by the salt string, followed by a final NUL byte (0x00):
    <tt>H = SHA-512(taxid || 0x00 || salt || 0x00)</tt>. Here, <tt>taxid</tt> is the
    UTF-8 string obtained by percent-decoding the <tt>taxid-enc</tt> path segment.
    This produces the <tt>hash-donor-id</tt>. The verification app will contact the
    base in the endpoint <tt>/donation-statement</tt> with the year and the hash-donor-id. 

    The <tt>hash-donor-id</tt> must be encoded using Base 32 U Crockford
    encoding <xref target="base32-U-crockford"/>.

    
    <list style="symbols">
      <t>Endpoint: /donation-statement</t>
      <t>Method: GET</t>
<t>Syntax: base/donation-statement/{year}/{hash-donor-id}</t>
<t>Contact: N/A</t>
<t>References: [this.I-D]</t>
</list>


Servers implementing the donation-statement endpoint MUST respect the
following syntax; all three fields (<tt>total-field</tt>, <tt>sig-field</tt>, <tt>pub-field</tt>) MUST be included.

The amount is a string formed first of the currency (in capital
letters) then ":" and then the value (can be an integer or a decimal
number).

   <sourcecode>
        <![CDATA[
json-object     = "{" ws field-list ws "}"

field-list      = field *(ws "," ws field)
field           = total-field / sig-field / pub-field

; Allow any order of the three fields
total-field     = DQUOTE "total" DQUOTE ws ":" ws DQUOTE currency ":" value DQUOTE
sig-field       = DQUOTE "donation_statement_sig" DQUOTE ws ":" ws DQUOTE signature DQUOTE
pub-field       = DQUOTE "donau_pub" DQUOTE ws ":" ws DQUOTE signature DQUOTE  ; same format as signature

currency        = 1*(%x41-5A)   ; A-Z uppercase letters
value           = int / decimal
int             = ["-"] 1*DIGIT
decimal         = ["-"] 1*DIGIT "." 1*DIGIT

signature       = 1*(ALPHA / DIGIT / "=")

; Common tokens
ws              = *WSP
DQUOTE          = %x22  ; "
WSP             = %x20 / %x09
DIGIT           = %x30-39
ALPHA           = %x41-5A / %x61-7A
        ]]>
      </sourcecode>

      

Example of an element of USD 100.00 :
   <sourcecode>
        <![CDATA[
{
   total: "USD:100",
   donation_statement_sig: "SIGNATURE",
   donau_pub: "EDDSA_PUBLIC_KEY"
}
        ]]>
      </sourcecode>


  </t>
</section>
<section anchor="signature-total-available" title="Signature and
						    total are available">
  <t>
    The verification app MUST verify that the signature corresponds to
    the claimed values.

    If the information is not in the URI, the verification app MUST download the total and the signature from the
    base using the GET /donation-statement/ endpoint <xref
    target="get-donation-statement"/>. Otherwise, it SHOULD use the
    value given in the URI. 

    The verification of the signature is done using EdDSA as
    specified in <xref target="RFC8032" />.

    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):

    <ul>
      <li>size (4 bytes): 32-bit unsigned integer with the total length of the signed data in bytes.</li>
      <li>purpose (4 bytes): 32-bit unsigned integer with the constant value <tt>1500</tt>.</li>
      <li>total value (8 bytes): integer part as an unsigned 64-bit integer.</li>
      <li>total fraction (4 bytes): fractional part as an unsigned 32-bit integer in units of 1/100000000.</li>
      <li>currency (12 bytes): ASCII, left-aligned and zero-padded to 12 bytes.</li>
      <li>donor hash H (64 bytes): <tt>H = SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>.</li>
      <li>year (4 bytes): 32-bit unsigned integer (the donation year).</li>
    </ul>
    
</t>
</section>

<section anchor="signature" title="Signature of the donation statement ">
  <t>
    The server signing the donation statement  <bcp14>MUST</bcp14> use the Sign(d,message) procedure implemented as defined in <xref target="RFC8032" />.
  </t>
  <figure anchor="figure_signature_data" title="The binary representation of the data to sign">
       <artwork name="" type="" align="left" alt=""><![CDATA[
0
]]></artwork>
     </figure>



     <t>
         The signature over the public key covers a 32-bit pseudo header
         conceptually prefixed to the EXPIRATION and BDATA fields.
         The wire format is illustrated
         in <xref target="figure_rrsigwithpseudo"/>.
        </t>
        <figure anchor="figure_rrsigwithpseudo">
          <name>The Wire Format Used for Creating the Signature of the RRBLOCK</name>
          <artwork name="" type="" alt="">
0     8     16    24    32    40    48    56
+-----+-----+-----+-----+-----+-----+-----+-----+
|         SIZE          |       PURPOSE (1500)  |
+-----+-----+-----+-----+-----+-----+-----+-----+
|                TOTAL value                    |
+-----+-----+-----+-----+-----+-----+-----+-----+
|       TOTAL  fraction |     CURRENCY          |
+-----+-----+-----+-----+                       +
|                                               |
+-----+-----+-----+-----+-----+-----+-----+-----+
|              SHA512 of the donor ID           |
/                                               /
/                                               /
+-----+-----+-----+-----+-----+-----+-----+-----+
|       YEAR            |
+-----+-----+-----+-----+
           </artwork>
        </figure>
        <dl newline="false">
          <dt>SIZE:</dt>
          <dd>
           A 32-bit value containing the length of the signed data in bytes
           in network byte order.
         </dd>
          <dt>PURPOSE:</dt>
          <dd>
           A 32-bit signature purpose flag in network byte order. The value of this
           field <bcp14>MUST</bcp14> be 1500.  It defines the context in which
           the signature is created so that it cannot be reused in other parts
           of the protocol that might include possible future extensions.
           The value of this field corresponds to an entry in the
           GANA "GNUnet Signature Purposes" registry <xref target="GANA"/>.
         </dd>
          <dt>TOTAL value:</dt>
          <dd>
            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),
         </dd>
          <dt>TOTAL fraction:</dt>
          <dd>
	    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.
	  </dd>
          <dt>TOTAL currency</dt>
          <dd>
            A string representing the currency. ASCII, left-aligned and zero-padded to exactly 12 bytes.
         </dd>
          <dt>HASH:</dt>
          <dd>The SHA512 hash code for the donor ID.</dd>
          <dt>YEAR:</dt>
          <dd>The year on a 32 bit unsigned integer in big endian.</dd>
        </dl>
       </section>

<section anchor="signature-verification" title="Signature verification for a donation statement">
  <t>
The signature verification step is taking the data presented in the figure <xref target="figure_signature_data" /> as
input. Signature MUST be verified using the EdDSA scheme described in
<xref target="RFC8032" /> the procedure is Verify(zk,message,signature). Public key and signature are given
encoded in Base 32 U Crockford MUST first be decoded to get a binary
out of it.
  </t>
  <t>
           The Sign(d,message) and Verify(zk,message,signature) procedures <bcp14>MUST</bcp14>
           be implemented as defined in <xref target="RFC8032" />.
         </t>
     
</section>

<section anchor="base32-U-crockford" title="Base 32 representation of
					    binary data">
<t>All binary data MUST be encoded to be transmitted. For encoding, one
MUST use the Base32 U Crockford encoding. This is a variation of the
base32 encoding <xref target ="RFC4648" />. This encoding is presented
in details in the appendix of the RFC for GNU Name System <xref target="RFC9498" />
</t>
<t>
The encoding works similarly to the standard, but uses another Base 32
Alphabet. The new alphabet is given in the Table <xref target="figure_base32_encoding" />, below.
</t>

<figure anchor="figure_base32_encoding" title="The Base 32 Encoding Alphabet.">
  <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[
Value Encoding  Value Encoding  Value Encoding  Value Encoding
    0 0             9 9            18 J            27 V
    1 1            10 A            19 K            28 W
    2 2            11 B            20 M            29 X
    3 3            12 C            21 N            30 Y
    4 4            13 D            22 P            31 Z
    5 5            14 E            23 Q
    6 6            15 F            24 R           (pad) =
    7 7            16 G            25 S
    8 8            17 H            26 T

    ]]>
  </artwork>
</figure>
	 
<t>	 
To prevent optical character reading (OCR) problems, a system decoding binary data encoded with base 32 U Crockford MUST
accept the codes presented in the Table <xref target="figure_base32_decoding"/>, below. System reading a U
MUST evaluate it as a V. 
</t>

  <figure anchor="figure_base32_decoding" title="The Base 32 Decoding Alphabet.">
        <artwork name="" type="" align="left" alt=""><![CDATA[
Value Encoding  Value Encoding  Value Encoding  Value Encoding
    0 0             9 9            18 J|j          27 V|v|u|U
    1 1|i|I|l|L    10 A|a          19 K|k          28 W|w
    2 2            11 B|b          20 M|m          29 X|x
    3 3            12 C|c          21 N|n          30 Y|y
    4 4            13 D|d          22 P|p          31 Z|z
    5 5            14 E|e          23 Q|q
    6 6            15 F|f          24 R|r        (pad) =
    7 7            16 G|g          25 S|s
    8 8            17 H|h          26 T|t
    ]]></artwork>
      </figure>
	 


        </section>

        <section anchor="appendix-test-vectors" title="Appendix. Test Vector: Verify from URI">
            <t>
                This appendix shows how to verify a donation statement starting from a
                received URI. Public key is fetched from the Donau base.
            </t>

            <figure>
                <artwork><![CDATA[
Example URI:
donau://donau.test.taler.net/2025/123%2F456%2F789/AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0?total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30

Extracted fields:
- base: donau.test.taler.net
- year: 2025
- taxid: 123%2F456%2F789
- taxid (decoded): 123/456/789
- salt: AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0
- total: TESTKUDOS:1
- signature: ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30

Fetched public key for year 2025 from https://donau.test.taler.net/keys:
- pub: 2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG
        ]]></artwork>
            </figure>

      <t>Verification steps:</t>
      <list style="numbers">
        <t>Input (URI):<br/>
<tt>donau://donau.test.taler.net/2025/123%2F456%2F789/AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0?total=TESTKUDOS:1&amp;sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30</tt></t>
        <t>Parse fields:<br/>
          - base: <tt>donau.test.taler.net</tt><br/>
          - year: <tt>2025</tt> (4 digits)<br/>
          - taxid-enc: <tt>123%2F456%2F789</tt><br/>
          - taxid (UTF-8, percent-decoded, no trimming): <tt>123/456/789</tt><br/>
          - salt (ASCII): <tt>AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0</tt><br/>
          - total (amount string): <tt>TESTKUDOS:1</tt><br/>
          - sig (Crockford Base32, algorithm ED25519): <tt>B14WGS...XGY30</tt></t>
        <t>Public signing key (Crockford Base32) (from <tt>/keys</tt>):<br/>
<tt>2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG</tt></t>
        <t>Donor hash <tt>H</tt> = <tt>SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>:<br/>
          - length: 64 bytes<br/>
          - hex:<br/>
<tt>4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b</tt><br/>
          - Crockford Base32 (for HTTP endpoints):<br/>
<tt>9AN1W5QWBFJ4GGNRCERZ2ZD3JABCMYSN56KJ1R8TQAE8QNS9YYGY5ERBK8WW0B973PJXT5DEMSPEJPZ7HF5F706Y36GBVF6RMY9RY6R</tt></t>
        <t>Amount encoding (<tt>TALER_AmountNBO</tt>):<br/>
          - currency (12 bytes): <tt>"TESTKUDOS"</tt> then <tt>0x00</tt> x 3<br/>
          - value (uint64 BE): <tt>1</tt> -> <tt>0x0000000000000001</tt><br/>
          - fraction (uint32 BE): <tt>0</tt> -> <tt>0x00000000</tt></t>
        <t>Signed message <tt>M</tt> layout (network byte order, total 100 bytes):<br/>
          - [0000..0003] 4 bytes <tt>size</tt>: <tt>0x00000064</tt><br/>
          - [0004..0007] 4 bytes <tt>purpose</tt>: <tt>0x000005DC</tt> (1500)<br/>
          - [0008..0015] 8 bytes <tt>amount.value</tt>: <tt>0x0000000000000001</tt><br/>
          - [0016..0019] 4 bytes <tt>amount.fraction</tt>: <tt>0x00000000</tt><br/>
          - [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/>
          - [0032..0095] 64 bytes <tt>i.hash</tt>: donor hash <tt>H</tt><br/>
          - [0096..0099] 4 bytes <tt>year</tt>: <tt>0x000007E9</tt> (2025)</t>
        <t>Message <tt>M</tt> (hex, 100 bytes):<br/>
<tt>00000064 000005dc 0000000000000001 00000000 544553544b55444f53000000 4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b 000007e9</tt></t>
        <t>Signature (ED25519, Crockford Base32 -> bytes):<br/>
          - length: 64 bytes<br/>
          - R (first 32 bytes, hex):<br/>
<tt>5849c864837bece5a254ce0dc0c51434e2956c6393e2339b06b5054ac490c088</tt><br/>
          - S (last 32 bytes, hex):<br/>
<tt>fb05891b09fb36020f0bcf132acfee46632411de4e4bf27fe972f891fd7b0f0c</tt></t>
        <t>Public key (Ed25519, Crockford Base32 -> bytes):<br/>
          - length: 32 bytes<br/>
          - hex:<br/>
<tt>13f15131534b68de38253f0d1f24f856f3607d8c6011d4d4d268a9339023ef7f</tt></t>
        <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>
        <t>Negative check (optional): flip one bit of <tt>M</tt> or <tt>sig</tt> and repeat; verification MUST fail.</t>
      </list>
    </section>





</middle>

<back>

  <references title="Normative References">

    &RFC2119;

    &RFC3986;

    &RFC8174;

    &RFC5234;

    &RFC6234; 

    &RFC8032; 

    &RFC9498; 

    &RFC8905; 


  </references>

  <references title="Informational References">

    &RFC4648; 


 <reference anchor="GANA" target="https://gana.gnunet.org/">
   <front>
       <title>GNUnet Assigned Numbers Authority (GANA)</title>
      <author><organization>GNUnet e.V.</organization>
      </author>
       <date month="April" year="2020" />
   </front>
 </reference>

  </references>

<!-- Change Log
v00 2022-11-11  CG   Initial version
  -->
</back>
</rfc>
