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:
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;
- }
}