Сразу скажу - в исходники не смотрел (для android-приложений их нетрудно вытащить), но в целом принципиальный алгоритм представляется таким:
currentAuthCode = function GetAuthCode (initValue[userInput], tValue[currentTime])
Здесь initValue - код, который вы копируете из приложения при инициализации пароля (текстом или распознавая QR), tValue - цифровое значение текущего момента времени. Для удобства пользователя этот параметр округляется до минуты - чтобы результат в течении минуты не менялся. А результат, собственно, и будет ключом аутентификации.
Раз в минуту происходит пересчет, причем не только по изменившемуся tValue, но и по новому initValue, взятому из предыдущего currentAuthCode:
currentAuthCode = function GetAuthCode (currentAuthCode, tValue)
хотя в упрощенной версии алгоритма может использоваться только новое значение времени, это уберет итерации перерасчетов.
Таким образом, зная начальный код, время его ввода, и промежуток между обновлениями, можно получить код действительный в любое другое время (и только в это время). Эта информация есть в приложении, в котором происходит аутентификация, при проверке кода оно сверяет его по той же функции.
Для проверки - выставьте на устройстве с приложением-аутентификатором неверное время, генерируемые им коды перестанут работать.