I've generated human-friendly checksums by taking bits from an MD5 checksum and using them into index into a list of words. For example:
: nr@yorkie 7012 ; md5words /home/nr/.profile
overextend moonscape cucumbers outsmarting
The code is about 40 lines of Lua not counting the word list, which is included in the script so as to produce identical results on every system.
EDIT:
In your application, you want to generate 50,000 keys. You can do it by something like this:
for ((i=1; i<=50000; i++))
do
echo "this is my secret phrase $i" | md5words
done
Using this procedure with a different secret phrase produces these keys:
Chisinau Phaethon customs Martina
commensurate freewill logical cambered
kamikazes Creighton Dobro's Alonzo
medallion's jesters goofy keystones
Anaxagoras martial Medina's Hon's
acclimatized chirping Cleopatra's mascaras
buoyant nuclear lumbering disagreements
dampens Philby cloak drollness
These keys are difficult to forge: the word list has almost 100,000 words on it, so there are 10^20 possible 4-word sequences. If you have 100,000 codes, the chance of somebody being able to guess a code at random are one in 10^15. If you put a throttle on the number of keys people are allowed to try, say one key every 0.3 seconds, you won't have a problem.
If I were deploying this idea in your application, I would prune the word list to something shorter, maybe only 10,000 words that are very commonly recognized. Even after losing a factor of 10^4 the numbers are vastly in your favor---the chance of guessing a key would be 1 in 100 billion.