The default is to store keys in memory. This isn't ideal at all and the RFCs recommend an HSM (see Key Providers) In cases where this isn't possible, or is deemed overkill after a security review, OtpSharp comes with a default in memory key. be aware that this model is subject to potential key leakage. Effort has been taken to protect the keys in memory using the windows memory protection API, but this is imperfect in many ways.
There is a static class that can be used to generate new shared secret keys to use. It uses the a .net cryptographic random number generator.
var key = KeyGeneration.GenerateKey(20);
This will give you a byte array of 20 bytes. You can specify the length of the key that you wish to generate.
The RFC uses key sizes based on the hash algorithm used. If you wish to follow the RFC default keys sizes used then you can simply provide the hash algorithm that you are using to get a key of the example size.
var key = KeyGeneration.GenerateKey(OtpHashMode.Sha512);
In Memory Protection
The library contains a class called InMemoryKey. This can be used to protect a key while it is in memory. It uses the .net MemoryProtection class to do this. It will keep the key encrypted while in memory as much as possible. There are small windows of time where the plaintext key is needed (such as the generation of a one time password. The protected key class will attempt to minimize these windows as much as possible and overwrite the copy of the plaintext key that was created when done.
The Totp and Hotp classes both accept a protected key instance as the key parameter in the constructor.