taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

commit 8269c32574d406b927603511df197d0468215e5f
parent 5f7654d5ba3524e039d18792e2a00a4df63c0a0a
Author: Bohdan Potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Wed,  8 Oct 2025 23:58:03 +0200

[donau-verificator] update to latest lsd0013

Diffstat:
Mdonau-verificator/src/main/cpp/verification.cpp | 18+++++++++++-------
Mdonau-verificator/src/main/java/net/taler/donauverificator/MainActivity.java | 4+++-
Mdonau-verificator/src/main/java/net/taler/donauverificator/Results.java | 30++++++++----------------------
3 files changed, 22 insertions(+), 30 deletions(-)

diff --git a/donau-verificator/src/main/cpp/verification.cpp b/donau-verificator/src/main/cpp/verification.cpp @@ -23,7 +23,7 @@ // needed for libsodium #include <sodium/crypto_sign.h> -#include <sodium/crypto_hash_sha256.h> +#include <sodium/crypto_hash_sha512.h> /** * Maximum legal 'value' for an amount, based on IEEE double (for JavaScript compatibility). @@ -384,7 +384,7 @@ TALER_string_to_amount_nbo (const char *str, */ struct DONAU_HashDonorTaxId { - unsigned char hash[256 / 8]; + unsigned char hash[512 / 8]; }; @@ -578,18 +578,22 @@ Java_net_taler_donauverificator_Results_ed25519_1verify( struct DONAU_DonauSignatureP sig; struct DONAU_HashDonorTaxId h_donor_tax_id; - crypto_hash_sha256_state state; - crypto_hash_sha256_init(&state); + crypto_hash_sha512_state state; + crypto_hash_sha512_init(&state); unsigned int tax_length; for (tax_length = 0; tax_id[tax_length]!= '\0'; ++tax_length); unsigned int salt_length; for (salt_length = 0; salt[salt_length]!= '\0'; ++salt_length); - crypto_hash_sha256_update(&state, tax_id, tax_length); - crypto_hash_sha256_update(&state, salt, salt_length); + // H = SHA-512( UTF8(tax_id) || 0x00 || UTF8(salt) || 0x00 ) + crypto_hash_sha512_update(&state, tax_id, tax_length); + unsigned char sep = 0x00; + crypto_hash_sha512_update(&state, &sep, 1); + crypto_hash_sha512_update(&state, salt, salt_length); + crypto_hash_sha512_update(&state, &sep, 1); - crypto_hash_sha256_final(&state, h_donor_tax_id.hash); + crypto_hash_sha512_final(&state, h_donor_tax_id.hash); struct DONAU_DonationStatementConfirmationPS confirm = { .purpose.purpose = htonl (1500), diff --git a/donau-verificator/src/main/java/net/taler/donauverificator/MainActivity.java b/donau-verificator/src/main/java/net/taler/donauverificator/MainActivity.java @@ -42,8 +42,10 @@ import androidx.core.content.ContextCompat; import net.taler.donauverificator.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { +// private static final String DEBUG_DONATION_STATEMENT = +// "donau://example.com/megacharity/1234/2025/7560001010000/1234?total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28&pub=K641W1CZM7DRSV184M8CPM3Z8MZRBYYJMNYMJK70FTYJHBPX21J0"; private static final String DEBUG_DONATION_STATEMENT = - "donau://example.com/megacharity/1234/2025/7560001010000/1234?total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28&pub=K641W1CZM7DRSV184M8CPM3Z8MZRBYYJMNYMJK70FTYJHBPX21J0"; + "donau://donau.test.taler.net/2025/123%2F456%2F789/AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0?total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30"; private int PERMISSIONS_REQUEST_CAMERA = 0; private ActivityMainBinding binding; private CodeScanner mCodeScanner; diff --git a/donau-verificator/src/main/java/net/taler/donauverificator/Results.java b/donau-verificator/src/main/java/net/taler/donauverificator/Results.java @@ -57,7 +57,7 @@ public class Results extends AppCompatActivity { private static final String TAG = "Results"; - // lsd0013 format: donau://host/year/taxid/salt?total=...&sig=ED25519:... + // Format: donau://base/year/taxid-enc/salt?total=...&sig=ED25519:... // CrockfordBase32 encoded: SIGNATURE, PUBLICKEY private String uriScheme; @@ -393,8 +393,6 @@ public class Results extends AppCompatActivity { hostDisplay = buildHostDisplay(); - hostDisplay = buildHostDisplay(); - String yearCandidate = segments.get(yearIndex); if (yearCandidate != null) { yearCandidate = yearCandidate.trim(); @@ -405,11 +403,9 @@ public class Results extends AppCompatActivity { year = yearCandidate; + // Tax ID: use exact UTF-8 bytes from percent-decoded segment without trimming String taxIdCandidate = segments.get(yearIndex + 1); - if (taxIdCandidate != null) { - taxIdCandidate = taxIdCandidate.trim(); - } - if (!isValidTaxId(taxIdCandidate)) { + if (isEmpty(taxIdCandidate)) { return SignatureStatus.MALFORMED_ARGUMENT; } taxId = taxIdCandidate; @@ -418,7 +414,7 @@ public class Results extends AppCompatActivity { if (saltCandidate != null) { saltCandidate = saltCandidate.trim(); } - if (!isDigitsOnly(saltCandidate)) { + if (isEmpty(saltCandidate)) { return SignatureStatus.MALFORMED_ARGUMENT; } salt = saltCandidate; @@ -571,9 +567,12 @@ public class Results extends AppCompatActivity { } private String computeDonorHash(String taxIdValue, String saltValue) throws NoSuchAlgorithmException { - MessageDigest digest = MessageDigest.getInstance("SHA-256"); + MessageDigest digest = MessageDigest.getInstance("SHA-512"); + // H = SHA-512( UTF-8(taxId) || 0x00 || UTF-8(salt) || 0x00 ) digest.update(taxIdValue.getBytes(StandardCharsets.UTF_8)); + digest.update(new byte[]{0}); digest.update(saltValue.getBytes(StandardCharsets.UTF_8)); + digest.update(new byte[]{0}); byte[] hash = digest.digest(); return CrockfordBase32.encode(hash); } @@ -661,17 +660,4 @@ public class Results extends AppCompatActivity { } return true; } - - private boolean isValidTaxId(String value) { - if (isEmpty(value)) { - return false; - } - for (int i = 0; i < value.length(); i++) { - char ch = value.charAt(i); - if (!(Character.isLetterOrDigit(ch) || ch == '-' || ch == '.')) { - return false; - } - } - return true; - } }