Txn set checksum and report account selector checksum are verification and auditing tools to ensure that generated reports are using correct and known inputs.
For overal information, see Accounting Auditing and example reports listed below:
-
Reports with audit metadata
-
Reports in JSON format for Server and Client API
Transaction set checksum (txn set checksum) is secure and cryptographically strong hash and proof of presence of transactions which are used to do accounting calculations.
Txn set checksum is based on UUID of Txn, and it is hash function’s result of those UUIDs. Hash is calculated so that it is possible to verify it easily with external tools. See Journal Format and description of Transaction metadata.
Txn set checksum is calculated based on following algorithm:
-
Txn’s UUIDs are collected as canonical 8-4-4-4-12 lower case hexadecimal strings.
-
Sorted list of UUID stings is fed to hash function so that each UUID is separated with single newline (
'\n', ASCII0x0A) character. -
Resulting hash function hash is Txn Set Checksum
See contrib for example script (txn-set-checksum.sh) how to calculate that with standard UNIX command line tools.
Each transaction must have unique UUID. Presence of UUID and uniqueness are enforced.
Txn set checksum verifies that same set of transactions (UUIDs) is used for calculations,
but it does not verify actual content of used transactions. If and when content verification is needed,
then Tackler’s git storage backend could be used for that. In that case,
content verification is done by combining reported git’s commit id and txn set checksum.
Together commit id and txn set checksum creates tamper proof verification of used transaction data.
To re-verify previous tackler report, it is possible to use git commit id (from old report) as an input reference. See Usage Guide and Git Storage Guide for further info.
Report account selectors core.reporting.accounts and core.reports.<report-type>.accounts are used
to select which accounts are included into reports. Selected accounts affect calculated and reported totals.
Report account selector checksum is secure and cryptographically strong hash of account selector, e.g. it can be used as fingerprint of used account selector.
Account selector checksum is calculated based on following algorithm:
-
Sorted list of account selectors is fed to hash function (e.g. SHA-256) so that each selector is separated with single newline (
'\n', ASCII0x0A) character. -
Resulting hash is Account Selector Checksum
New configuration group for core:
-
✓ group: 'auditing'
-
✓ String:
hashJavaSE Tech notes, Security -
✓ boolean:
txn-set-checksum
-
If txn-set-checksum is true, then all transactions must have valid :uuid:-metadata field.
See
Journal Format
for further info.
Following changes are needed
-
✓ enforce uuid
-
✓ Verify presence of UUID at parse time
-
✓ Hard error if UUID is missing during txn set checksum calculation
This is either internal error or logic error within usage of Server API
-
-
✓ calculate txn set checksum
-
✓ calculate account selector checksum
Tackler supports hash functions provided by Java platform, most notably SHA-256 … SHA-512 algorithms on Java 8,
and SHA3-256 … SHA3-512 on Java 11+.
See MessageDigest on:
Txn set checksum with external tools
(
find "$1" -type f -name '*.txn' | \
xargs -n100 grep -h ';:uuid:'
) | \
sed -E 's/[[:space:]]+;:uuid:[[:space:]]+([a-fA-F0-9-]+)[[:space:]]*/\1/' | \
tr 'A-F' 'a-f' | \
sort | \
sha256sum
val txns = rawTxns.flatten.sorted(OrderByTxn)
val txnHash = txns.map(_.header.uuid match {
case Some(uuid) => uuid.toString
case None => throw new TacklerException("missing uuid")
})
.sorted
.foldLeft(MessageDigest.getInstance("SHA-256"))({
case (hash, uuid) => {
hash.update((uuid + "\n").getBytes("UTF-8"))
hash
}
}).digest()
def hex2str(hash: Array[Byte]) = {
hash.map(b => "%02x".format(0xff & b)).mkString
}
Api changes to server or client interfaces.
Changes to server API
-
✓ Txn set checksum data and mechanism to TxnData
-
✓ Report account selector checksum
Changes to reports or reporting
Changes to balance report
-
✓ txn set checksum
-
✓ text
-
✓ json
-
-
✓ account selector checksum
-
✓ text
-
✓ json
-
Changes to balance group report
-
✓ txn set checksum
-
✓ text
-
✓ json
-
-
✓ account selector checksum
-
✓ text
-
✓ json
-
Changes to exports or exporting
Changes to equity export
-
✓ Audit / verification material to equity export?
-
✓ General metadata (e.g. Git metadata)
-
✓ txn set checksum
-
✓ account selector checksum
-
✓ Empty selector, e.g. "select all"
-
✓ Active selector
-
-
-
✓ ./readme.adoc: Update TEP index
-
✓ ../../README.adoc: is it a new noteworthy feature?
-
✓ [../../CHANGELOG]: add new item
-
✓ Does it warrant own T3DB file?
-
✓ update ../../tests/tests.adoc
-
✓ update ../../tests/check-tests.sh
-
✓ Add new T3DB file ../../tests/tests-1007.yml
-
-
✓ User docs
-
✓ user manual
-
✓ tackler.conf
-
✓
hash -
✓
txn-set-checksum
-
-
✓ examples
-
-
✓ Developer docs
-
✓ API changes
-
✓ Server API changes
-
✓ Client API changes
-
-
There are several possibilities to enhance txn set checksum:
-
Option to turn off uuid duplicate detection
-
Support SHA-3, this should be possible by changing JDK version: http://openjdk.java.net/jeps/287
-
✓ Make this configurable
-
-
External listing which includes all used transaction UUIDs
-
There could be a separate, actual content hash which is calculated over some normalization of Txn data.
Normal, ok-case tests to validate functionality:
-
✓ test basic txn set checksum
-
✓ test audit staff alone, without git
-
-
✓ different hash algorithms
-
✓ test configuration settings of different hash algorithm
-
✓ reporting with different hash algorithm
-
-
✓ reports
-
✓ { balance, balance-group, register } x { text, json }
-
-
✓ Account selector checksum
-
✓ None (All pass)
-
✓ { balance, balance-group, register } x { text, json }
-
✓ { equity } x { txn }
-
-
✓ All have same global selector
-
✓ { balance, balance-group, register } x { text, json }
-
✓ { equity } x { txn }
-
-
✓ Each report has own selector, global is set
-
✓ balance
-
✓ balane-group
-
✓ register
-
✓ equity
-
-
-
✓ exports
-
✓ test equity
-
✓ test case with all metadata (txn-set-checksum, git-storage, filters, account-selector-hash)
-
✓ feed generated equity back (e.g. check validity of format)
-
-
-
✓ test that upper case UUIDs result same txn-set-checksum as lower case UUIDs
-
✓ test that filtered Txns has correct (new) txn set checksum
-
✓ test case with all metadata (txn-set-checksum, git-storage, filters, account-selector-hash)
-
✓ metadata in case that there are no matching accounts to be reported
-
✓ Filter Txns multiple times, check correct metadata / txn-set-checksum
Various error cases:
-
✓ e:
txn-set-checksum = true, but missing uuid-
✓ e: at parsing time / txn creation
-
✓ e: at hash calculation time
-
-
✓ e: check that git storage reports txn path in case of error
-
✓ e: Duplicate UUID
-
✓ e: verify that duplicate UUID is detected
-
✓ e: verify count of duplicates
-
-
✓ e: Check that invalid UUID is detected and rejected/errored
-
✓ e:
java.util.UUID.fromStringis not very smart
https://bugs.openjdk.java.net/browse/JDK-8159339
https://bugs.openjdk.java.net/browse/JDK-8165199
https://bugs.openjdk.java.net/browse/JDK-8216407
-
// valid
scala> java.util.UUID.fromString("69439222-4d8b-4d0e-8204-50e2a0c8b664")
res1: java.util.UUID = 69439222-4d8b-4d0e-8204-50e2a0c8b664
// invalid
scala> java.util.UUID.fromString("694aaaaa39222-4d8b-4d0e-8204-50e2a0c8b664")
res2: java.util.UUID = aaa39222-4d8b-4d0e-8204-50e2a0c8b664
-
✓ e: invalid hash type
Add new perf test target for txn set checksum
-
❏ perf test of txn set checksum
-
❏ with txn set checksum
-
❏ without txn set checksum
-