To ensure unique inode between instances we will have this flow:
when app starts it generates a unique random u8 (unique in data_dir/seq), use this as instance_id
also have a param --instance-id
save that id keyring and use it next time
if app is uninstalled when we start next time we will generate a new random id
generate nonce like instance_id | inode_seq
keep inode_seq in data_dir/seq/instance_id/inode
when generating inode first increment and save the inode_seq and then use that in inode
This reduces the number of inodes to 288,230,376,151,711,743, which is more than enough for us.
A possible problem:
Consider this example: one uses your program, creates a backup of the data, keeps using the program. If they restore the backup, then they will restart from an earlier counter, and reuse the same inode.
To mitigate this we could keep the inode_seq in keyring also and use max(keyring, app_data).
An alternative to counters is to have some logic to assign unique IDs to blocks, and use that ID to derive a nonce. You may get some inspiration on how to do that from https://en.wikipedia.org/wiki/Disk_encryption_theory, in particular the ESSIV section.
If you're concerned about nonce reuse, you might want to look into XChaCha20-Poly1305, which allows longer nonces.
Some popular constructs often used for disk encryption are AES-XTS and HBSH. You'll find it useful to research why they're used specifically for disk encryption.
To ensure unique inode between instances we will have this flow:
u8
(unique indata_dir/seq
), use this asinstance_id
--instance-id
keyring
and use it next timeinstance_id | inode_seq
inode_seq
indata_dir/seq/instance_id/inode
inode_seq
and then use that in inodeThis reduces the number of inodes to 288,230,376,151,711,743, which is more than enough for us.
A possible problem:
To mitigate this we could keep the
inode_seq
inkeyring
also and usemax(keyring, app_data)
.