Why not just store the salt with the data in the same file? Its not as though the program needs to maintain the files' binary compatibility with anything since the encrypted file isn't supposed to be readable by any other program other than the decryption program.
What makes dealing with key pairs hard for the lay user?
If the issue is "they have to transport them to use the crypto on systems other than their own": We should not be teaching lay-users (or non-lay-users) to enter passphrases or use private keys on untrusted systems.
For using multiple trusted systems, having the client software support multiple keypairs (like OpenSSH) or providing an easy way read the key off removable media (like an encrypted thumb drive) are great.
What about making the user choose two passphrases, which are concatenated together by the tool? Cracking a single passphrase may be easy, but cracking two concatenated passphrases is significantly harder.
E.g. password 1: "the quick brown fox jumps over the lazy dog"
Password 2: "jack be nimble jack be sick"
Final result, used to derive a keyfile: "the quick brown fox jumps over the lazy dogjack be nimble jack be sick"
Notice how "quick" was switched with "sick" in the last word. Now there's no pattern that can be easily cracked. If we force a user to explicitly do something like that, then this can still work.
That example was chosen intentionally to be weak. It shows that even with two relatively weak passphrases, the result is still somewhat strong. If we add extra requirements on top of that, such as forcing the user to use numbers and capitalizations, then the result should be sufficiently unique.
There's no difference between that and just requiring the user to use a longer password.
Anyone trying to attack the system will just program their cracker to be more likely to try concatenating words together awkwardly in the password somewhere.
It's easier for humans to remember two distinct passwords with individual complexity requirements than one gigantic passphrase.
By forcing the user to choose two passphrases which are then concatenated, the result is one gigantic passphrase that a cracker can't easily crack, yet is easy for humans to remember. It seems like this solves the problem of rainbow tables.
A keylogger could still break this system. But if an adversary has planted a keylogger, they could've simply stolen your keyfile.
No, because then the person generating their table just takes that into account. It's slighly harder, but not noticeably so compared to how secure it needs to be.
It seems like as long as the complexity of the passphrase is sufficient, then a rainbow table can't be effective. For example, a 128-bit random AES key is a kind of passphrase that's generally not susceptible to a rainbow table attack (though it's very hard for humans to remember). So the problem here is, how do you force the user to make their passphrase sufficiently complex?
Passphrases also don't protect against keyloggers, which is a downside of this approach.
You force the password to be sufficiently complex by doing what you said: creating it (pseudo)randomly. The aforementioned 128 bit random AES key is robust, assuming the PRNG is solid. A user-provided password utilizing the human mind as its PRNG will never come close.