0
$\begingroup$

I have a scenario with a user that needs to operate on common data from multiple devices but the link to the server is often offline. Unfortunately in the environment, I trust anything not directly in arms reach of the user about as much as gas-station sushi (server included). The data it's self is not really on its own uber-sensitive, but there is potential for use in social engineering attacks.

Requirements:

  1. The user must explicitly unlock the device to read/write the data.
  2. Devices need to be able to operate on data without an active connection to the server so they exclusively operate on local data that will background sync.
  3. E2E encryption since the security of the device at rest or the server cannot be guaranteed.
  4. Not all records are necessarily on every device.

Current approach:

  1. I am currently using libsodium because I feel it will keep me from doing lower-level stuff wrongly, but open to better approaches. It must have interop with Javascript and C++ though.
  2. The local device generates a stronger key using a password hash like Argon2 to act as a secret key for a libsodium crypto_secretbox.
  3. During setup/provisioning the user uploads a common private key and puts that in the crypto_secretbox.
  4. Use that public/private key pair with a crypto_box to access the actual record.

Problem:

Assuming that a station is currently offline and that the password used to generate the local passphrase may have been comprimised is there any feasible way to keep that device from possibly reading or writing any new data upstream and not mess up any other devices that might be offline at the time? I am resigned to the fact that all local records are exposed.

Assumptions:

  1. I am more than likely "doing it wrong."
  2. The passphrase is of reasonable quality and can be hashed into a more secure key with something that has a time/memory/cpu penalty to discourage brute force attacks.
  3. I can trust the users, but I cannot trust anything that happens when they are not around.
  4. Any device with contact to the server can read/write every record on the server.
  5. Locks only keep honest people out, I just don't want my module to be the weakest link.

Rough outline current code:

passphrase = read_terminal(...);
private_key_encrypted = load_record(...);
public_key = load_record(...);

key = pwhash(passphrase);
if (secretbox_open(private_key, private_key_encrypted, passphrase) != 0) {
   exit(); // caclulated password hash didn't match
}

shared_secret_key = null;
if (box_beforenm(shared_secret_key, public_key, private_key) != 0) {
  exit(); // decrypted private key doesn't match public key of data
}

// process records
encrypted_record = load_record(...);
record = null;
if (box_open_afternm(record, encrypted_record, shared_secret_key) != 0) {
  exit(); // message tampered
}

// ... do something with record

box_afternm(encrypted_record, record, shared_secret_key);
save_record(encrypted_record,...);

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.