Проблема защиты всегда меня интересовала, не важно, через какой порт предполагалось защищаться: COM,LPT,USB...
Вот какие варианты защиты я встречал: таксофонная карта получает от таксофона запрос из 6 байт, и выдает ответ из 2-х байт. Ответ зависит не только от запроса, но и от количества единиц на карточке. Таксофон тоже высчитывает ответ и сравнивает с получнным. Злоумышленник может проанализировать ответы и построить таблицу, но ее размер будет 2^48=280 триллионов(!) слов. И это только для одного значения счетчика!
Для компьютера такая защита не совсем подходит: взломщик найдет процедуру хеширования и сопрет.
Больше всего мне понравилась такая защита (не аппаратная): код полиморфный, защита от отладки, на анализ уйдет не один вечер. А программа стоит 200 руб. Такая тактика работает: я не нашел ни одного кряка к той программе!

Чего делать не стоит, так это обращаться к ключу только в момент загрузки. Программная защита и то понадежнее будет.
Хороша идея динамической дешифрации кода: отладочное прерывание вызывается после каждой инструкции и изменяет код впереди стоящей команды. Причем ключ дешифровки меняется каждые 100 микросекунд. Но это из вотчины ДОС-приложений, в Win с прерываниями гораздо сложнее...
По поводу усложнения анализа обмена и составления таблиц вопросов-ответов могу посоветовать шифровать запрос случайной величиной, которая в дальнейшем отсеется. Тогда ключ не будет получать одинаковых запросов, и понять принцип его работы будет сложно. А если еще и ответы шифровать случайной величиной...