lsd0013

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

commit 3926051105b66e90b8202c3f86516d2795e6d639
parent 7700e03cba8277ef975e07deb5da81a4431e3397
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon,  3 Nov 2025 11:15:47 +0100

01 to master

Diffstat:
Mdraft-donau.xml | 466+++++++++++++++++++++++++++++++++++++++++++------------------------------------
1 file changed, 254 insertions(+), 212 deletions(-)

diff --git a/draft-donau.xml b/draft-donau.xml @@ -1,29 +1,11 @@ -<?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' ?> +<?xml version="1.0" encoding="UTF-8"?> +<rfc xmlns:xi="http://www.w3.org/2001/XInclude" + category="info" docName="draft-grothoff-donau-XX" + ipr="trust200902" submissionType="independent" version="3"> <!-- 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-01" - ipr="trust200902"> + <!-- FIXME ipr is copied from lsd0001, need to be updated --> - <front> + <front xmlns=""> <title abbrev="The 'donau' URI scheme"> The 'donau' URI scheme for validation of Donau donation statements. </title> @@ -32,11 +14,10 @@ <organization>Bern University of Applied Sciences</organization> <address> <postal> - <street>H&ouml;heweg 80</street> - <street></street> + <street>H&#246;heweg 80</street> <city>Biel/Bienne</city> - <code>CH-2501</code> - <country>CH</country> + <code>2501</code> + <country>CHE</country> </postal> <email>christian.grothoff@bfh.ch</email> </address> @@ -46,11 +27,10 @@ <organization>Bern University of Applied Sciences</organization> <address> <postal> - <street>H&ouml;heweg 80</street> - <street></street> + <street>H&#246;heweg 80</street> <city>Biel/Bienne</city> - <code>CH-2501</code> - <country>CH</country> + <code>2501</code> + <country>CHE</country> </postal> <email>emmanuel.benoist@bfh.ch</email> </address> @@ -61,11 +41,10 @@ <organization>Bern University of Applied Sciences</organization> <address> <postal> - <street>H&ouml;heweg 80</street> - <street></street> + <street>H&#246;heweg 80</street> <city>Biel/Bienne</city> - <code>CH-2501</code> - <country>CH</country> + <code>2501</code> + <country>CHE</country> </postal> <email>bohdan.potuzhnyi@bfh.ch</email> </address> @@ -77,17 +56,16 @@ <address> <postal> <street>7, rue de Mondorf</street> - <street></street> <city>Erpeldange</city> - <code>L-5421</code> - <country>Luxembourg</country> + <code>5421</code> + <country>LUX</country> </postal> <email>dold@taler.net</email> </address> </author> - <date day="21" month="October" year="2025" /> + <date day="22" month="October" year="2025" /> <!-- Meta-data Declarations --> <area>General</area> @@ -145,16 +123,18 @@ </front> -<middle> +<middle xmlns=""> -<section anchor="introduction" title="Introduction"> +<section anchor="introduction"> + <name>Introduction</name> <t> This document defines the 'donau' Uniform Resource Identifier (URI) <xref target="RFC3986" /> scheme for triggering interactions with Donau validators. </t> -<section title="Objective"> +<section> + <name>Objective</name> <t> A 'donau' URI always instructs a Donau validator to perform the validation of a Donau donation statement. @@ -172,7 +152,8 @@ </section> -<section title="Requirements Language"> +<section> + <name>Requirements Language</name> <t> The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and @@ -184,8 +165,8 @@ </section> -<section anchor="syntax" - title="Syntax of a 'donau' URI"> +<section anchor="syntax"> + <name>Syntax of a 'donau' URI</name> <t> This document uses the Augmented Backus-Naur Form (ABNF) of <xref target="RFC5234"/>. </t> @@ -193,8 +174,9 @@ <artwork type="abnf"><![CDATA[ ; Scheme and high-level structure scheme = "donau" / "DONAU" / "donau+http" / "DONAU+HTTP" - donau-URI = scheme "://" base "?" year-param "&" taxid-param "&" salt-param - ("&" total-param "&" sig-param)? + donau-URI = scheme "://" base "?" year-param "&" + taxid-param "&" salt-param + ("&" total-param "&" sig-param)? ; The base is the HTTP(S) origin plus optional path segments that ; identify the Donau REST API deployment. Everything before the last @@ -236,7 +218,8 @@ </figure> </section> -<section anchor="semantics" title="Semantics"> +<section anchor="semantics"> + <name>Semantics</name> <t> Even if RFC3986 <xref target="RFC3986"/> explicitly writes that scheme names are case-insensitive, lower and upper case variations are presented here to @@ -324,23 +307,43 @@ </t> </section> -<section anchor="examples" title="Examples"> +<section anchor="examples"> + <name>Examples</name> <figure> <artwork><![CDATA[ ; Minimal example with a simple base and simple taxid - donau://example.com/?year=2025&id=7560001010000&salt=1234&total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28 + donau://example.com/ + ?year=2025&id=7560001010000& + salt=1234& + total=EUR:15& + sig=ED25519: + H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1 + QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28 ; Example with percent-encoded taxid containing '/' - donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789&salt=1234&total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30 + donau://donau.test.taler.net/ + ?year=2025&id=123%2F456%2F789& + salt=1234& + total=TESTKUDOS:1& + sig=ED25519: + B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG2 + 1W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30 ; Example with a base URL that includes path components - donau://admin.ch/taxes/donau/?year=2025&id=7560001010000&salt=1234&total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28 + donau://admin.ch/taxes/donau/ + ?year=2025&id=7560001010000& + salt=1234& + total=EUR:15& + sig=ED25519: + H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1 + QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28 ]]> </artwork> </figure> </section> -<section anchor="verification" title="Verification of a Donau URI"> +<section anchor="verification"> + <name>Verification of a Donau URI</name> <t> The verification requires the Donau verification application to test if a given taxpayer is entitled to a tax reduction. @@ -362,7 +365,8 @@ </t> </section> -<section anchor="get-server-keys" title="Obtaining Donau Server Public Keys"> +<section anchor="get-server-keys"> + <name>Obtaining Donau Server Public Keys</name> <t> The verification app <bcp14>MUST</bcp14> obtain the signing public key corresponding to the base for the given year. @@ -376,31 +380,32 @@ The verification app <bcp14>SHOULD</bcp14> 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>References: [this.I-D]</t> - </list> + <ul> + <li>Endpoint: /keys</li> + <li>Method: GET</li> + <li>Syntax: base/keys</li> + <li>Syntax response: defined hereunder</li> + <li>References: [this.I-D]</li> + </ul> + <t> 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"/>. + </t> - <sourcecode> + <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 +; Core JSON tokens (simplified; assumes standard JSON dialect) +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 +EscapedChar = %x22 / %x5C / %x2F / %x62 / %x66 / + %x6E / %x72 / %x74 / "u" 4HEXDIG JSONNumber = [ "-" ] 1DIGIT *( DIGIT ) [ "." 1DIGIT *( DIGIT ) ] [ ( "e" / "E" ) [ "+" / "-" ] 1DIGIT *( DIGIT ) ] JSONBool = "true" / "false" @@ -408,42 +413,53 @@ JSONNull = "null" JSONArray = "[" [ JSONException *( "," JSONException ) ] "]" JSONObject = "{" [ JSONMember *( "," JSONMember ) ] "}" JSONMember = JSONString ":" JSONException -JSONException = JSONString / JSONNumber / JSONObject / JSONArray / JSONBool / JSONNull +JSONException = JSONString / JSONNumber / JSONObject / + JSONArray / JSONBool / JSONNull ; Specific DonauKeysResponse structure DonauKeysResponse = "{" JSONMemberSep "}" -JSONMemberSep = version , domain , base_url , currency , currency_fraction_digits , - donation_units , signkeys +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 +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 ) +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_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 ] +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 "}" +SignKey = "{" DQUOTE "key" DQUOTE ":" JSONObject "," + DQUOTE "year" DQUOTE ":" JSONNumber "}" ]]> </sourcecode> -Example, a response to a GET request to the <tt>/keys</tt> endpoint. - <sourcecode> + <t>Example, a response to a GET request to the <tt>/keys</tt> endpoint.</t> + <sourcecode> <![CDATA[ { "signkeys": [ @@ -456,13 +472,11 @@ Example, a response to a GET request to the <tt>/keys</tt> endpoint. } ]]> </sourcecode> - - - </t> </section> -<section anchor="get-donation-statement" - title="Donation Statement Retrieval"> + +<section anchor="get-donation-statement"> + <name>Donation Statement Retrieval</name> <t> If the Donau URI does not contain the total or the signature, the verification app <bcp14>MUST</bcp14> download them from the <tt>/donation-statement</tt> @@ -480,23 +494,26 @@ Example, a response to a GET request to the <tt>/keys</tt> endpoint. The hash of the donor taxpayer ID <tt>hash-donor-id</tt> <bcp14>MUST</bcp14> be encoded using Base 32 U Crockford encoding <xref target="base32-U-crockford"/>. + </t> - <list style="symbols"> - <t>Endpoint: /donation-statement</t> - <t>Method: GET</t> - <t>Syntax: base/donation-statement/{year}/{hash-donor-id}</t> - <t>References: [this.I-D]</t> - </list> + <ul> + <li>Endpoint: /donation-statement</li> + <li>Method: GET</li> + <li>Syntax: base/donation-statement/{year}/{hash-donor-id}</li> + <li>References: [this.I-D]</li> + </ul> -Servers implementing the donation-statement endpoint -<bcp14>MUST</bcp14> respect the -following syntax; all three fields (<tt>total-field</tt>, <tt>sig-field</tt>, <tt>pub-field</tt>) <bcp14>MUST</bcp14> be included. + <t> + Servers implementing the donation-statement endpoint + <bcp14>MUST</bcp14> respect the + following syntax; all three fields (<tt>total-field</tt>, <tt>sig-field</tt>, <tt>pub-field</tt>) <bcp14>MUST</bcp14> be included. -The total 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). + The total 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). + </t> - <sourcecode> + <sourcecode> <![CDATA[ json-object = "{" ws field-list ws "}" @@ -504,9 +521,12 @@ 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 +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 @@ -524,10 +544,8 @@ ALPHA = %x41-5A / %x61-7A ]]> </sourcecode> - - -Example of an element of USD 100.00 : - <sourcecode> + <t>Example of an element of USD 100.00 :</t> + <sourcecode> <![CDATA[ { "total": "USD:100", @@ -536,14 +554,11 @@ Example of an element of USD 100.00 : } ]]> </sourcecode> - - - </t> </section> -<section anchor="signature-total-available" - title="Verification if Signature and Total are Available"> +<section anchor="signature-total-available"> + <name>Verification if Signature and Total are Available</name> <t> The verification app <bcp14>MUST</bcp14> verify that the signature corresponds to the claimed values. @@ -560,22 +575,22 @@ Example of an element of USD 100.00 : The verification <bcp14>MAY</bcp14> 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 string, left-aligned with zero-padding on the right to 12 bytes.</li> - <li>hash of donor taxpayer ID (64 bytes): <tt>hash-donor-id = 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> + + <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 string, left-aligned with zero-padding on the right to 12 bytes.</li> + <li>hash of donor taxpayer ID (64 bytes): <tt>hash-donor-id = 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> </section> -<section anchor="signature" - title="Creating Donation Statement Signatures"> +<section anchor="signature"> + <name>Creating Donation Statement Signatures</name> <t> The server signing the donation statement <bcp14>MUST</bcp14> use the Sign(d,message) procedure implemented as defined in <xref target="RFC8032" />. </t> @@ -644,8 +659,8 @@ Example of an element of USD 100.00 : </dl> </section> -<section anchor="signature-verification" - title="Validating Donation Statement Signatures"> +<section anchor="signature-verification"> + <name>Validating Donation Statement Signatures</name> <t> The signature verification step is taking the data presented in the figure <xref target="figure_donausigwithpseudo" /> as input. @@ -664,8 +679,8 @@ Example of an element of USD 100.00 : </section> -<section anchor="base32-U-crockford" - title="Base 32 Representation of Binary Data"> +<section anchor="base32-U-crockford"> + <name>Base 32 Representation of Binary Data</name> <t> All binary data <bcp14>MUST</bcp14> be encoded to be transmitted. For encoding, one <bcp14>MUST</bcp14> use the Base32 U Crockford encoding. This is a variation of the @@ -677,7 +692,8 @@ Example of an element of USD 100.00 : 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."> + <figure anchor="figure_base32_encoding"> + <name>The Base 32 Encoding Alphabet.</name> <artwork name="" type="" align="left" alt="table where value between 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 misleading (OCR may not recognize them properly). Padding is the char ="><![CDATA[ Value Encoding Value Encoding Value Encoding Value Encoding 0 0 9 9 18 J 27 V @@ -701,7 +717,8 @@ Value Encoding Value Encoding Value Encoding Value Encoding System reading a <tt>U</tt> <bcp14>MUST</bcp14> evaluate it as a <tt>V</tt>. </t> - <figure anchor="figure_base32_decoding" title="The Base 32 Decoding Alphabet."> + <figure anchor="figure_base32_decoding"> + <name>The Base 32 Decoding Alphabet.</name> <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 @@ -719,7 +736,8 @@ Value Encoding Value Encoding Value Encoding Value Encoding </section> -<section anchor="security" title="Security Considerations"> +<section anchor="security"> + <name>Security Considerations</name> <t> Donau validators <bcp14>SHOULD</bcp14> support "<tt>donau+http://</tt>"-URIs only when run in developer or debug mode @@ -733,18 +751,18 @@ Value Encoding Value Encoding Value Encoding Value Encoding for instance on <tt>localhost</tt>. </t> <t> - Validator applications <bcp>MUST</bcp> include protections + Validator applications <bcp14>MUST</bcp14> include protections against repeated validations of the same donation statement with the same salt and year. Specifically, when summing up multiple donation statements for the same taxpayer and - tax year, the <bcp>MUST</bcp> keep enough state to add + tax year, the <bcp14>MUST</bcp14> keep enough state to add up the maximum total amounts per salt if multiple donation statements are submitted with the same salt. </t> </section> -<section anchor="iana" title="IANA Considerations"> +<section anchor="iana"> <name slugifiedName="name-iana-considerations">IANA Considerations</name> <t> IANA maintains the "Uniform Resource Identifier (URI) Schemes" @@ -752,7 +770,7 @@ Value Encoding Value Encoding Value Encoding Value Encoding requested to update that entry to reference this document when published as an RFC. </t> - <dl indent="3" newline="false" spacing="normal" pn="section-9-2"> + <dl indent="3" newline="false" spacing="normal"> <dt>Scheme name:</dt> <dd> donau</dd> <dt>Status:</dt> @@ -779,10 +797,63 @@ Value Encoding Value Encoding Value Encoding Value Encoding </middle> -<back> +<back xmlns=""> + + + + + <references anchor="refs"> + <name>Normative References</name> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/> + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5234.xml"/> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6234.xml"/> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8032.xml"/> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9498.xml"/> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8905.xml"/> + + + </references> + + <references> + <name>Informational References</name> + + <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml"/> + + + <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> + + <reference anchor="BaThesis" target="https://www.taler.net/papers/donau-thesis.pdf"> + <front> + <title>Tax-deductable Privacy-Preserving Donations</title> + <author initials="J.C." surname="Casaburi" fullname="Johannes Casaburi"> + <organization>Bern University of Applied Science, Bachelor Thesis</organization> + </author> + <author initials="L.M." surname="Matya" fullname="Lukas Matya"> + <organization>Bern University of Applied Science, Bachelor Thesis</organization> + </author> + </front> + </reference> + </references> -<section anchor="appendix-test-vectors" title="Appendix. Test Vector: Verify from URI"> +<section anchor="appendix-test-vectors"> + <name>Appendix. Test Vector: Verify from URI</name> <t> This appendix shows how to verify a donation statement starting from a received URI. Public key is fetched from the Donau base. @@ -791,7 +862,12 @@ Value Encoding Value Encoding Value Encoding Value Encoding <figure> <artwork><![CDATA[ Example URI: -donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789&salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0&total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30 +donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789& + salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0& + total=TESTKUDOS:1& + sig=ED25519: + B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21 + W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30 Extracted fields: - base: donau.test.taler.net @@ -800,7 +876,8 @@ Extracted fields: - taxid (decoded): 123/456/789 - salt: AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0 - total: TESTKUDOS:1 -- signature: ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30 +- signature: ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4 + GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30 Fetched public key for year 2025 from https://donau.test.taler.net/keys: - pub: 2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG @@ -808,103 +885,68 @@ Fetched public key for year 2025 from https://donau.test.taler.net/keys: </figure> <t>Verification steps:</t> - <list style="numbers"> - <t>Input (URI):<br/> -<tt>donau://donau.test.taler.net/?year=2025&amp;id=123%2F456%2F789&amp;salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0&amp;total=TESTKUDOS:1&amp;sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30</tt></t> - <t>Parse fields:<br/> + <ol> + <li>Input (URI):<br/> +<tt>donau://donau.test.taler.net/?year=2025&amp;id=123%2F456%2F789&amp; +salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0&amp; +total=TESTKUDOS:1&amp; +sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21 +W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30</tt></li> + <li>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>Hash of the donor taxpayer ID <tt>hash-donor-id</tt> = <tt>SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>:<br/> + - sig (Crockford Base32, algorithm ED25519): <tt>B14WGS...XGY30</tt></li> + <li>Public signing key (Crockford Base32) (from <tt>/keys</tt>):<br/> +<tt>2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG</tt></li> + <li>Hash of the donor taxpayer ID <tt>hash-donor-id</tt> = <tt>SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>:<br/> - length: 64 bytes<br/> - hex:<br/> -<tt>4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b</tt><br/> +<tt>4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a 1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b</tt><br/> - Crockford Base32 (for HTTP endpoints):<br/> -<tt>9AN1W5QWBFJ4GGNRCERZ2ZD3JABCMYSN56KJ1R8TQAE8QNS9YYGY5ERBK8WW0B973PJXT5DEMSPEJPZ7HF5F706Y36GBVF6RMY9RY6R</tt></t> - <t>Total amount encoding (<tt>TALER_AmountNBO</tt>):<br/> +<tt>9AN1W5QWBFJ4GGNRCERZ2ZD3JABCMYSN56KJ1R8TQAE8QNS9YYGY5ERBK 8WW0B973PJXT5DEMSPEJPZ7HF5F706Y36GBVF6RMY9RY6R</tt></li> + <li>Total 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/> + - fraction (uint32 BE): <tt>0</tt> -> <tt>0x00000000</tt></li> + <li>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>: hash of donor taxpayer ID <tt>hash-donor-id</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/> + - [0096..0099] 4 bytes <tt>year</tt>: <tt>0x000007E9</tt> (2025)</li> + <li>Message <tt>M</tt> (hex, 100 bytes):<br/> +<tt>00000064 000005dc 0000000000000001 00000000 544553544b55444f53000000 4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b 9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b 000007e9</tt></li> + <li>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/> +<tt>fb05891b09fb36020f0bcf132acfee46632411de4e4bf27fe972f891fd7b0f0c</tt></li> + <li>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 <bcp14>MUST</bcp14> 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 <bcp14>MUST</bcp14> fail.</t> - </list> +<tt>13f15131534b68de38253f0d1f24f856f3607d8c6011d4d4d268a9339023ef7f</tt></li> + <li>Verification (expected): call <tt>crypto_sign_verify_detached(sig, M, 100, pubkey)</tt>. The result <bcp14>MUST</bcp14> indicate a valid signature for this vector.</li> + <li>Negative check (optional): flip one bit of <tt>M</tt> or <tt>sig</tt> and repeat; verification <bcp14>MUST</bcp14> fail.</li> + </ol> </section> - - - <references anchor="refs" 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> - - <reference anchor="BaThesis" target="https://www.taler.net/papers/donau-thesis.pdf"> - <front> - <title>Tax-deductable Privacy-Preserving Donations</title> - <author initials="J.C." surname="Casaburi" fullname="Johannes Casaburi"> - <organization>Bern University of Applied Science, Bachelor Thesis</organization> - </author> - <author initials="L.M." surname="Matya" fullname="Lukas Matya"> - <organization>Bern University of Applied Science, Bachelor Thesis</organization> - </author> - </front> - </reference> - </references> +<section numbered="false"> + <name>Acknowledgements</name> + <t> + The authors thank Ted Hardie for his comments on an earlier version of the draft. + This work was funded in part by the European Commission through the + Horizon Europe program under project number 101135475 (TALER). It also + has received funding from the Swiss State Secretariat for Education, + Research and Innovation (SERI). + </t> +</section> <!-- Change Log v00 2025-10-17 CG Initial version