By ShaRose - 11 August 2016 12:40 AM
I have an idea that could be implemented into Reflect v7, and I will admit that the usefulness is likely something that would be used in an enterprise setting, but I feel like I should put it out there in case anyone else thinks of a good use-case.
Right now, the only way to encrypt a backup is via a password, but said password has to be kept in a reversible format in order to work (if being saved as a scheduled task). I generally try to avoid this wherever possible, so I had the idea of using public key based cryptography.
The idea is that when setting up a scheduled backup, Reflect would generate an RSA or Elliptic Curve keypair. This would be used to encrypt a (random) AES-256 key for actually encrypting the backup. The private key (for decrypting) would be encrypted with a password.
This means that should the keypair be found, you could encrypt new backups but you can't access older ones. Furthermore, as an example, if you generated an ed25519 keypair with an encrypted private key it's only 537 bytes, so you could easily embed the entire thing (in an encrypted state so you can't use a backup to make other, valid, backups) into the backup's metadata.
This also opens the ability to have the backup encrypted so that multiple users can decrypt it with unique credentials: simply encrypt the AES key with different public keys.
In comparison, right now as far as I know the flow is as follows:
Get password -> use PBKDF2 with salt to generate encryption key -> store salt in metadata, use encryption key to encrypt the backup
My idea changes it to be more like this:
Note: Private key should be stored encrypted. Public key should be kept plaintext. There should also be an encrypted blob with both the public and private keys encrypted stored, encrypted with the same key as the private key itself is.
Generate random encryption key -> encrypt encryption key with public key(s) -> store encrypted copy(s) of encryption key in metadata -> optionally store copies of encrypted blobs in metadata -> encrypt backup with encryption key
I hope I'm explaining the idea so that people can understand, but I thought it'd be an interesting idea, particularly for enterprises (the key could be encrypted with both the computer's public key and a domain admin's public key, for example).
By Stephen - 11 August 2016 9:57 AM
Thanks for posting.
I have raised a feature request for the development team to evaluate.
By jphughan - 2 September 2017 4:54 PM
@dyhs drew my attention to this thread in a thread that I created. I've read through your proposal a few times now and I'm still not sure I correctly understand the design you're proposing. For the purposes of my post here, I'm going to skip the details of the specific ciphers you mention as well as the ancillary benefits you're suggesting, i.e. "old backup invalidation" and multi-user decryption, and instead focus solely on the core security design. Please let me know if I'm understanding your proposal correctly:
- When a user is setting up a definition file and provides an encryption password, Reflect generates an RSA/Elliptic Curve key pair. Let's name them:
Key A = Public Key
Key B = Private Key
- Broadly speaking, the intent is to use Key A (indirectly) for encrypting backups and Key B (indirectly) for decrypting them, which would allow Key A to be stored in a definition file (in cleartext) to create backups, without introducing the risk that a malicious actor could use that to find a way to decrypt backups.
- Every time a backup runs, Reflect generates a unique, random AES-256 key (call it Key C), which will be used to directly encrypt the data being backed up. Key C would be encrypted by Key A (available in the definition file) and that encrypted result would be stored in the backup file being generated. Because Key C was encrypted with Key A, it can now only be decrypted by Key B.
- Key B would be encrypted by a user-supplied password, and that encrypted result would also be stored in every backup file that was generated. The end result would be that in order to decrypt the data in the backup file, the user would supply a password, which would decrypt Key B. Key B would then be used to decrypt Key C, and Key C would be used to decrypt the actual data in the backup file.
Question: If the ciphertext version of Key B (generated by encrypting with the user-supplied password) needs to be added to every backup file, it has to be stored somewhere -- where would you store that? In the definition file? If you store it elsewhere, that would affect the "portability" of your backup jobs to other PCs.
By ShaRose - 2 September 2017 7:35 PM
That's pretty much exactly what I was saying, yes. Same with your question: the encrypted private key and public key would be stored in the definition. I'll post in the other thread with a bit more (hopefully better explained) detail.
By jphughan - 2 September 2017 11:02 PM
I like this design, and I admit it's superior from a security standpoint to the idea I posted in my thread that I linked earlier, since my design simply makes it more difficult to recover the user-supplied password, whereas this design makes it absolutely impossible. This design would also address the two threats I called out in my own thread. The only drawback to this approach I can think of compared to my "salted password" proposal (other than potentially more engineering effort to implement) is that if Reflect no longer has a way to recover the user-supplied password on its own, then its automatic system restore feature would break, or would at least require some retooling so that the user-supplied password could be temporarily stored in a recoverable manner for this specific case.
Well anyhow, even if nothing comes of this in Reflect, I've enjoyed thinking through both my own implementation and yours. Nice work!