Yubikey + GPG – быстрый старт
Требования к безопасности непрерывно растут, так как взломщики постоянно эволюционируют и все лучше умеют красть данные. Доступ к данным становится все более ценным — это могут быть живые деньги, секретная информация или доступ в инфраструктуру, интеллектуальную собственность или пользовательские данные (которые эта инфраструктура обрабатывает). А это – очень большие деньги. А иногда и вовсе вопрос жизни и смерти целой структуры.
Простой системы логин/пароль уже недостаточно, чтобы обеспечить надежную защиту, и даже система с ассиметричными ключами имеет уязвимости:
- ключ можно выкрасть. Он будет шифрован, но пароль можно подобрать. Это медленный процесс, но взломщику может повезти, особенно, если у него есть какая-то информация об особенностях пароля. Например, он знает его точную длинну.
- Для того, чтобы ключ можно было использовать — он должен быть расшифрован. Обычно расшифрованый ключ хранится в оперативной памяти, но при наличии доступа к памяти его можно украсть. Атака сложная, но если ключ по-настоящиему ценный — реальная.
Для того, чтобы сделать работу с шифрованием надежной и безопасной – были придуманы аппаратные носители ключей. Концепция выглядит просто – шифровальный ключ не покидает аппаратного токена (обычно это смарт-карта с чипом), и если операционной системе требуется произвести какое-то действие с шифрованием (зашифровка, расшифровка, подпись) – данные передаются в аппаратный ключ. Ключ выполняет действия (если проситель имеет право на такие действия) и выдает результат.
В этой статье я расскажу, как настроить Yubikey 4 для работы с GPG и использовать его для стандартных действий (шифрование, расшифровка, авторизация по SSH).
Yubikey — это именно такой ключ. Это простой, удобный и понятный для начинающего ключ-смарткарта в форм-факторе USB-флешки. Классический Yubikey 4 выпускается в двух форм-факторах – обычная “полноразмерная” флешка или “нано-ключ” — вставленный в комп наноключ практически не выступает из порта, что удобно, если ключ подключен постоянно и не должен изыматься. Yubikey 4 выпускается как под USB2 Type A, так и под USB3 Type C порт, что удобно для обладателей новых ноутбуков (macbook pro touch bar). Так же компания Yubiko выпускает Yubkey Neo — Yubkey с поддержкой NFC (для смартфонов), но со сниженным максимальным размером ключа (2048 бит вместо 4096 для Yubikey 4).
Кроме GPG, Yubikey может работать как стандартная smart-карта и генерировать одноразовые пароли (TOTP/HOTP). В этой статье будет описана только настройка под GPG.
Предварительные настройки
Для того, чтобы использовать gpg для Yubikey — потребуется сам gpg. Пользователи MacOS могут использовать MacGPG. Пользователям Linux ничего делать не надо — gpg входит в поставку ОС. Чтобы gpg создал нужные ему папки — запускаем gpgtool. Он предложит создать новый приватный ключ — игнорируем, просто закрываем программу.
После установки пакета надо добавить в ~/.bashrc следующие строки:
export GPG_TTY="$(tty)" export SSH_AUTH_SOCK=$(/usr/local/MacGPG2/bin/gpgconf --list-dirs agent-ssh-socket) if ! pgrep gpg-agent &> /dev/null; then echo "gpg-agent not running" /usr/local/MacGPG2/bin/gpg-agent --homedir /Users/YOUR_LOGIN/.gnupg --daemon fi
Обратите внимание, что вам нужно поменять логин на свой
Также надо указать pinentry и включить поддежку ssh-agent в файле ~/.gnupg/gpg-agent.conf :
default-cache-ttl 600 max-cache-ttl 7200 pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac enable-ssh-support
Теперь можно подключить yubikey. Проверим, что карта подключилась и определилась:
tungsten> gpg --card-edit Reader . Yubico Yubikey 4 OTP U2F CCID Application ID . D2760001240102010006070171690000 Version . 2.1 Manufacturer . Yubico Serial number . 07017169 Name of cardholder: [not set] Language prefs . [not set] Sex . unspecified URL of public key : [not set] Login data . [not set] Signature PIN . not forced Key attributes . rsa2048 rsa2048 rsa2048 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 0 3 Signature counter : 0 Signature key . [none] Encryption key. [none] Authentication key: [none] General key info. [none] gpg/card>
Отлично, карта есть, можно настраивать. Первое, что нужно поменять — pin-коды карты. У карты два pin-кода:
- User PIN — отвечает за проверку авторизации самой карты. Его нужно ввести, чтобы использовать ключ (зашифровать, расшифровать данные или авторизоваться)
- Admin PIN — отвечает за настройку карты. Он позволяет управлять содержимым карты или ее настройками.
Не смотря на названия, PIN-коды — это полноценные пароли длинной до 127 символов включительно. Пароли имеют ограничения — там нельзя использовать символы национальных алфавитов и спецсимволы. То есть – можно только английские буквы и цифры. Кроме того, Admin PIN должен быть не менее 8 символов длинной. Yubikey никак не предупредит об этом, но pin короче 8 символов просто не запишется. При смене PIN-кода спросят старый PIN. PIN-коды по умолчанию:
- User PIN: 123456
- Admin PIN: 12345678
Переключимся в админ-режим и поменяем пины:
gpg/card> admin Admin commands are allowed gpg/card> passwd gpg: OpenPGP card no. D2760001240102010006070171690000 detected 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? 1 PIN changed. 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? 3 PIN changed. 1 - change PIN 2 - unblock PIN 3 - change Admin PIN 4 - set the Reset Code Q - quit Your selection? q
Небольшая ремарка про PIN-ы. Карта считает все неуспешные попытки использования PIN-кода. Если ввести PIN-код неправильно несколько раз подряд – он блокируется. User PIN можно разблокировать с помощью Admin PIN. Заблокированный Admin PIN разблокировать нельзя никак. Карту можно полностью сбросить командой factory-reset — при этом все ее содержимое будет безвозвратно уничтожено. Для factory-reset никакие пин-коды не нужны. Счетчик неуспешных попыток сбрасывается, если ввести PIN правильно.
Теперь рекомендуется персонализировать карту — внести в нее информацию о себе. Это мало на что влияет, но имя будет отображаться в диалоге ввода PIN (что облегчает идентификацию карты). Кроме того, общую информацию о карте можно прочитать без кода – это может помочь, если вы потеряете карту. Важный параметр — url, это адрес, с которого можно будет скачать ваш публичный ключ:
gpg/card> name Cardholder's surname: Rudnitskiy Cardholder's given name: Paul gpg/card> sex Sex ((M)ale, (F)emale or space): M gpg/card> lang Language preferences: en gpg/card> login Login data (account name): logan gpg/card> url URL to retrieve public key: https://prudnitskiy.pro/gpg.pub
Карта готова и теперь можно экспортировать ключ на нее или создать ключ прямо на ней. Если у вас нет ключа — я рекомендую прямо на карте его и создавать. Если ключ уже есть – ниже есть раздел о том, как перенести ключ на карту
Генерация ключа на Yubikey
Перед тем, как создавать ключ — я рекомендую поменять его размер. По умолчанию Yubikey создает один мастер-ключ и два сабключа:
- Master + Certify
- SUB1 — Encryption
- SUB2 – Authentication
Все три ключа по умолчанию — RSA2048. RSA4096 выглядит намного интереснее. Поменяем:
gpg/card> key-attr Changing card key attribute for: Signature key Please select what kind of key you want: (1) RSA (2) ECC Your selection? 1 What keysize do you want? (2048) 4096 The card will now be re-configured to generate a key of 4096 bits Changing card key attribute for: Encryption key Please select what kind of key you want: (1) RSA (2) ECC Your selection? 1 What keysize do you want? (2048) 4096 The card will now be re-configured to generate a key of 4096 bits Changing card key attribute for: Authentication key Please select what kind of key you want: (1) RSA (2) ECC Your selection? 1 What keysize do you want? (2048) 4096 The card will now be re-configured to generate a key of 4096 bits gpg: error changing key attribute for key 3: Bad PIN Changing card key attribute for: Authentication key Please select what kind of key you want: (1) RSA (2) ECC Your selection? 1 What keysize do you want? (2048) 4096 The card will now be re-configured to generate a key of 4096 bits
Внимание! Если у вас Yubikey Neo — вы не можете использовать 4096-битные ключи.
Теперь (наконец-то!) приступим к созданию ключей. Вопрос политики устаревания ключей в целом довольно дискуссионный, и тут я не могу ничего порекомендовать. В данном примере я создам мастер-ключ с бесконечным сроком жизни, а саб-ключи мы потом отредактируем и они будут жить по 5 лет. В процессе создания ключа GPG спросит пароль для шифрования off-card резервной копии. Она вам потребуется, если вы потеряете физический ключ. Off-card экспортируется только subkey для шифрования (capability — E). Остальные sub-ключи и мастер-ключ останутся на карте и вынуть оттуда их нельзя. Процесс генерации ключа зависит от выбранного размера ключа (4096 бит будет генерироваться дольше, чем 2048):
gpg/card> generate Make off-card backup of encryption key? (Y/n) y Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: Paul Rudnitskiy Email address: [email protected] Comment: YBKey You selected this USER-ID: "Paul Rudnitskiy (YBKey) [email protected]>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O [. ] We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: Note: backup of card key saved to '/Users/logan/.gnupg/sk_8E0418955A55C1A8.gpg' gpg: key 9ECF9961A551A45B marked as ultimately trusted gpg: revocation certificate stored as '/Users/logan/.gnupg/openpgp-revocs.d/707C3210B50A430B555DD6AC9ECF9961A551A45B.rev' public and secret key created and signed.
Ключ готов. Резервную копию забираем из /Users/logan/.gnupg/sk_8E0418955A55C1A8.gpg (у вас место будет другим) и прячем в надежное место. Пароль резервной копии тоже прячем в надежное место, но другое. Обязательно удалите резервную копию с той машины, где вы работаете с ключом.
Проверим, что ключ сгенерировался:
gpg/card> list Reader . Yubico Yubikey 4 OTP U2F CCID Application ID . D2760001240102010006070171690000 Version . 2.1 Manufacturer . Yubico Serial number . 07017169 Name of cardholder: Paul Rudnitskiy Language prefs . en Sex . male URL of public key : [not set] Login data . logan Signature PIN . not forced Key attributes . rsa4096 rsa4096 rsa4096 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 0 3 Signature counter : 4 Signature key . 707C 3210 B50A 430B 555D D6AC 9ECF 9961 A551 A45B created . 2018-08-07 07:58:18 Encryption key. 062A ABF7 6FB0 8EF4 0E97 4B47 8E04 1895 5A55 C1A8 created . 2018-08-07 07:58:18 Authentication key: 6A41 D75C 2B56 41FC A7F4 8DBE CC02 AF33 8EE7 E338 created . 2018-08-07 07:58:18 General key info. pub rsa4096/9ECF9961A551A45B 2018-08-07 Paul Rudnitskiy (YBKey) [email protected]> sec> rsa4096/9ECF9961A551A45B created: 2018-08-07 expires: never card-no: 0006 07017169 ssb> rsa4096/CC02AF338EE7E338 created: 2018-08-07 expires: never card-no: 0006 07017169 ssb> rsa4096/8E0418955A55C1A8 created: 2018-08-07 expires: never card-no: 0006 07017169
Все в порядке, уходим:
gpg/card> quit
Теперь зададим срок жизни сабключей. Он нужен для того, чтобы если по какой-то причине вы потеряли доступ к копии ключа – им нельзя было пользовать после истечения срока жизни ключа. Для этого надо выйти из режима редактирования карты и отредактировать ключ. Редактивровать мы будем SEC-ключ, в этом примере это 9ECF9961A551A45B:
Команда key NUM выберет ключ для редактирования. Чтобы снять выбор — нужно ввести ее повторно:
Меняем срок жизни:
Снимаем выделение первого ключа и меняем второй по аналогии:
gpg> key 1 sec rsa4096/9ECF9961A551A45B created: 2018-08-07 expires: never usage: SC card-no: 0006 07017169 trust: ultimate validity: ultimate ssb rsa4096/CC02AF338EE7E338 created: 2018-08-07 expires: 2023-08-06 usage: A card-no: 0006 07017169 ssb rsa4096/8E0418955A55C1A8 created: 2018-08-07 expires: never usage: E card-no: 0006 07017169 [ultimate] (1). Paul Rudnitskiy (YBKey) [email protected]> gpg> key 2 sec rsa4096/9ECF9961A551A45B created: 2018-08-07 expires: never usage: SC card-no: 0006 07017169 trust: ultimate validity: ultimate ssb rsa4096/CC02AF338EE7E338 created: 2018-08-07 expires: 2023-08-06 usage: A card-no: 0006 07017169 ssb* rsa4096/8E0418955A55C1A8 created: 2018-08-07 expires: never usage: E card-no: 0006 07017169 [ultimate] (1). Paul Rudnitskiy (YBKey) [email protected]> gpg> expire Changing expiration time for a subkey. Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 5y Key expires at Sun Aug 6 11:01:29 2023 MSK Is this correct? (y/N) y sec rsa4096/9ECF9961A551A45B created: 2018-08-07 expires: never usage: SC card-no: 0006 07017169 trust: ultimate validity: ultimate ssb rsa4096/CC02AF338EE7E338 created: 2018-08-07 expires: 2023-08-06 usage: A card-no: 0006 07017169 ssb* rsa4096/8E0418955A55C1A8 created: 2018-08-07 expires: 2023-08-06 usage: E card-no: 0006 07017169 [ultimate] (1). Paul Rudnitskiy (YBKey) [email protected]> gpg> save
Ключ на карте готов к использованию
Перенос существующего ключа на Yubikey
Этот раздел вам нужен, если у вас уже есть gpg-ключ и вы хотите его перенести на карту. Вы не сможете экспортировать приватный ключ с карты yubikey.
После того, как карта сконфигурирована, открываем режим редактирования ключа:
Ключи переносятся командой keytocard . На Yubikey есть только три слота под три типа (capability) ключа:
- Encryption key
- Authentication key
- Sign key
Если у вас больше ключей — то вы должны решить, какие ключи вы будете переносить. В примере выше — 2 sign ключа, по этому мастер мы переносить не будем — на yubikey уедут только три сабключа. Перед началом переноса ключей рекомендую сделать backup и положить его в безопасное место.
Выберем ключ для переноса:
После переноса снимем выделение с него:
По аналогии перенесем 2 и 3 ключи:
gpg> key 2 sec rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 usage: SC trust: ultimate validity: ultimate ssb rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 usage: E ssb* rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 usage: A ssb rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 usage: S [ultimate] (1). Paul Rudnitskiy [email protected]> gpg> keytocard Please select where to store the key: (3) Authentication key Your selection? 3 sec rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 usage: SC trust: ultimate validity: ultimate ssb rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 usage: E ssb* rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 usage: A ssb rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 usage: S [ultimate] (1). Paul Rudnitskiy [email protected]> gpg> key 2 sec rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 usage: SC trust: ultimate validity: ultimate ssb rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 usage: E ssb rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 usage: A ssb rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 usage: S [ultimate] (1). Paul Rudnitskiy [email protected]> gpg> key 3 sec rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 usage: SC trust: ultimate validity: ultimate ssb rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 usage: E ssb rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 usage: A ssb* rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 usage: S [ultimate] (1). Paul Rudnitskiy [email protected]> gpg> keytocard Please select where to store the key: (1) Signature key (3) Authentication key Your selection? 1 sec rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 usage: SC trust: ultimate validity: ultimate ssb rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 usage: E ssb rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 usage: A ssb* rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 usage: S [ultimate] (1). Paul Rudnitskiy [email protected]>
Все перенесено, сохраним и проверим:
gpg> save tungsten> gpg --card-edit Reader . Yubico Yubikey 4 OTP U2F CCID Application ID . D2760001240102010006070171690000 Version . 2.1 Manufacturer . Yubico Serial number . 07017169 Name of cardholder: [not set] Language prefs . [not set] Sex . unspecified URL of public key : [not set] Login data . [not set] Signature PIN . not forced Key attributes . rsa2048 rsa2048 rsa2048 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 0 3 Signature counter : 0 Signature key . 21F7 B93A 71CD F86D 649D 8D06 61BE BC77 84A8 3F16 created . 2018-08-08 14:51:38 Encryption key. 7A30 6771 BB74 204F 54D5 8A61 1200 D2BB 8DFB 614C created . 2018-08-08 14:51:38 Authentication key: DDB0 62D0 1BB4 4D01 3819 E450 0BC3 AD72 9F05 D736 created . 2018-08-08 14:54:07 General key info. pub rsa2048/61BEBC7784A83F16 2018-08-08 Paul Rudnitskiy [email protected]> sec# rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 ssb> rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 card-no: 0006 07017169 ssb> rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 card-no: 0006 07017169 ssb> rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 card-no: 0006 07017169
Обратите внимание, что мастер-ключ не лежит на карте – он пока еще хранится на компьютере (и внутри бэкапа). Имея доступ к мастер-ключу — можно редактировать срок жизни sub-ключа или отозвать (revoke) его. Очень важно хранить мастер в безопасности. Для этого мы вынесем его в холодное хранилище:
- у вас должна быть резервная копия мастер-ключа
- экспортируем публичный ключ
- удалим все секретные ключи с компьютера
- импортируем обратно публичный ключ, сделав его доверенным
Экспортируем публичный ключ:
gpg --export --armour 61BEBC7784A83F16 > pub.asc
Уберем из компьютера yubikey и удалим приватный ключ:
gpg --edit-key 61BEBC7784A83F16 gpg> delkey
импортируем публичный ключ обратно:
gpg --import < pub.asc
повысим ему уровень доверия
gpg --edit-key 61BEBC7784A83F16 gpg> trust sec rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 usage: SC trust: ultimate validity: ultimate ssb rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 usage: E ssb rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 usage: A ssb rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 usage: S [none] (1). Paul Rudnitskiy [email protected]> Please decide how far you trust this user to correctly verify other users' keys (by looking at passports, checking fingerprints from different sources, etc.) 1 = I don't know or won't say 2 = I do NOT trust 3 = I trust marginally 4 = I trust fully 5 = I trust ultimately m = back to the main menu Your decision? 5 Do you really want to set this key to ultimate trust? (y/N) y
Теперь проверим, что ключи на карте видны:
tungsten> gpg --card-edit Reader . Yubico Yubikey 4 OTP U2F CCID Application ID . D2760001240102010006070171690000 Version . 2.1 Manufacturer . Yubico Serial number . 07017169 Name of cardholder: [not set] Language prefs . [not set] Sex . unspecified URL of public key : [not set] Login data . [not set] Signature PIN . not forced Key attributes . rsa2048 rsa2048 rsa2048 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 0 3 Signature counter : 0 Signature key . 21F7 B93A 71CD F86D 649D 8D06 61BE BC77 84A8 3F16 created . 2018-08-08 14:51:38 Encryption key. 7A30 6771 BB74 204F 54D5 8A61 1200 D2BB 8DFB 614C created . 2018-08-08 14:51:38 Authentication key: DDB0 62D0 1BB4 4D01 3819 E450 0BC3 AD72 9F05 D736 created . 2018-08-08 14:54:07 General key info. pub rsa2048/61BEBC7784A83F16 2018-08-08 Paul Rudnitskiy [email protected]> sec# rsa2048/61BEBC7784A83F16 created: 2018-08-08 expires: 2022-08-08 ssb> rsa2048/1200D2BB8DFB614C created: 2018-08-08 expires: 2022-08-08 card-no: 0006 07017169 ssb> rsa2048/0BC3AD729F05D736 created: 2018-08-08 expires: 2022-08-07 card-no: 0006 07017169 ssb> rsa2048/FAF7641B57B14FF2 created: 2018-08-08 expires: 2022-08-07 card-no: 0006 07017169
Отлично, ключи видны, можно пользоваться.
Выводы
Использование gpg-ключа с карты практически ничем не отличается от использования ключа без карты. Для авторизации по ssh с использованием ключа вам потребуется RSA pubkey. Он создается от gpg subkey A (Auth capability). Если вы меняете auth-ключ – ssh-ключ поменяется тоже, имейте ввиду. Чтобы его получить - достаточно набрать команду ssh-add -L
ssh-add -L ssh-rsa AAAAB***************************** cardno:00007017169
Комментарий cardno подскажет, что ключ был импортирован из yubikey
На каждую попытку использовать ключ yubikey будет требовать ввод User PIN. Yubikey весьма безопасен и надежен, если не делать глупых ошибок в его использовании и применении. И разумеется - нельзя забывать о бэкапах.
Двухэтапная аутентификация в браузере с помощью USB-токена U2F

U2F — открытый протокол универсальной 2-факторной аутентификации, разработанный FIDO Alliance.
В альянс входят компании Google, PayPal, Lenovo, MasterCard, Microsoft, NXP ,Visa и другие.
Протокол поддерживается браузером Chrome с версии 38. Работает из коробки без драйверов в Windows/MacOS/Linux.
На текущий момент поддерживается сервисами Google, LastPass, WordPress.
В статье описывается опыт использования токена Yubikey NEO с поддержкой NFC и OpenPGP card, недостатки двухфакторной аутентификации по SMS.
Почему двухэтапная аутентификация по SMS бывает опасна
Сейчас очень популярна двухэтапная аутентификация при помощи SMS или звонка.
Безусловно, это удобно, и такая дополнительная проверка в большинстве случаев эффективна. Для защиты от автоматизированных атак, фишинга, подбора паролей, вирусов, восстановления утраченного доступа и прочего.
Но в случае, если ваша персона стала мишенью профессиональных мошенников, привязанный телефон может сыграть роковую роль. Чаще всего телефонный номер, к которому привязан аккаунт не является секретом, обычно это основной контактный номер. Почти все сервисы сообщают его первые или последние цифры любому желающему, если попытаться восстановить доступ к аккаунту. Поэтому выяснить номер связанный с аккаунтом несложно.
Узнать, на кого оформлен номер в России не составляет большого труда. Достаточно почитать эксперимент ребят из Roem.ru.
Получив персональные данные владельца номера, мошенники рисуют поддельную доверенность, водительские права или паспорт, и отправляются в ближайший филиал оператора сотовой связи.
Полномочия перевыпустить SIM-карту имеет любой рядовой сотрудник самого захудалого салона мобильной связи.
Забавно, что у большинства операторов в профиле абонента нет даже фотографии владельца номера, хотя паспорт они зачем-то ксерят. То есть достаточно нарисовать паспорт с совпадающими реквизитами и вклеить подходящую фотографию.
У операторов есть опция запрета перевыпуска SIM-карты по доверенности, однако это иллюзорная защита, потому как номера успешно перевыпускаются по поддельным водительским правам и паспортам.
Как запретить действия по доверенности для Мегафон, Билайн, МТС
Мегафон:
moscow.megafon.ru/help/servic. sti.html#21123
Для подключения услуги наберите на телефоне команду *105*508#.
Отключить услугу может только владелец номера при личном визите в салон «МегаФона» с документом, удостоверяющим личность.
Билайн
moskva.beeline.ru/customers/help/safe-beeline/ugrozy-mobilnykh-moshennikov/zapret-deystvyi-po-doverenosti
Для установки запрета необходимо обратиться в один из офисов «Билайн» с паспортом или позвонив по номеру 0611.
МТС
При личном визите в офис попросить, чтобы в комментариях к номеру указали, что все действия имеет право совершать только владелец с паспортом.
В Украине ситуация еще хуже, так как большинство номеров анонимны.
У оператора Kyivstar для перевыпуска SIM-карты требуется показать чек последнего пополнения счета и назвать три номера, на которые совершались звонки.
Хорошие сервисы, например, многие банки, сохраняют вместе с телефонным номером еще и IMSI (International Mobile Subscriber Identity) — уникальный идентификатор SIM-карты. В случае, если IMSI изменился, то привязка номера считается аннулированной и процедуру привязки нужно пройти заново.
К сожалению, таких сервисов не очень много.
Проверить IMSI любого номера можно с помощью HLR-запроса smsc.ru/testhlr
Рецепт для параноиков: у smsc.ru есть удобные библиотеки для Python, PHP, Perl, Ruby, Java, C#, Delphi, C++, позволяющие, в том числе, посылать HLR-запросы. Можно проверять IMSI своих номеров, например, два раза в сутки, и в случае его изменения бить тревогу. При самом дорогом тарифе один запрос стоит 0.2 рубля, выходит примерно 150 рублей в год за один номер. Через эту же библиотеку можно послать SMS с тревогой. Рекомендую 😉
Существуют и другие способы обхода подтверждения через мобильный телефон, такие как установка переадресации, перехват голосовой почты и т.д. Но их описание выходит за рамки данной статьи.
Устрашающие истории пострадавших в результате перевыпуска SIM-карт
U2F — FIDO Universal 2nd Factor
По задумке U2F аутентификатором выступает аппаратный модуль: USB-токен, SIM-карта или NFC брелок, который хранит ключи и самостоятельно выполняет криптографические операции. При этом ключи предустановлены при производстве и никогда не покидают токен.
- Пользователь авторизуется на веб-сайте/в приложении с помощью логина-пароля
- Сервер проверяет учетные данные и, если они верны, генерирует челендж для токена и отправляет его пользовательской программе, в данном случае, браузеру
- Браузер передает челендж токену, который может затребовать на свое усмотрение действия от пользователя. В моем случае это прикосновение пальцем к контактной площадке. Но это может быть, например, ввод пинкода, биометрическая проверка или вообще отсутствие таковых
- Токен возвращает программе ответ, который передается на сервер
- Аутентификация выполнена
На текущий момент поддержка U2F есть в Google Chrome, начиная с 38 версии. Вероятно, в ближайшее время будет добавлена в FireFox.
Уже поддерживается для авторизации в аккаунтах Google и Lastpass, есть плагин для WordPress, Django и библиотеки на разных языках.
Модули для Linux PAM, OpenSSH и прочего.
Таблица сервисов поддерживающих OTP/U2F авторизацию — www.dongleauth.info
Полезные ссылки
Личный опыт использования токена Yubikey NEO
Самые продвинутые U2F устройства производит компания Yubico.
Дистрибьютор в России — yubico.ru
Я купил самый навороченный на текущий момент брелок — Yubikey NEO.

- OpenPGP smartcard — определяется как ICCID ридер со вставленной OpenPGP картой версии 2.0
- NFC — можно использовать со смартфонами и как ключ для СКУД. Может работать как карта Mifare Classic в режиме эмуляции
- OTP и TimeOTP — определяется как hid клавиатура и по нажатию вводит одноразовый пароль. Time Based OTP через программный апплет (замена google authenticator)
- PIV smartcard — (Personal Identity Verification) американский государственный стандарт смарткарт
По дефолту устройство работает в режиме Yubico OTP (фирменный протокол одноразовых паролей), определяется только как HID-клавиатура и по нажатию на кнопку печатает одноразовые пароли на основе ID устройства.
Включить режим U2F нужно через фирменную утилиту, которая есть под Windows/Mac/Linux.

Я предпочел включить режимы U2F и ICCID для работы в качестве OpenPGP карты.

На этом все. U2F сразу работает, никакие драйвера устанавливать не требуется.
Проверить работу можно в демо-приложении demo.yubico.com/u2f
Привязка токена к Google-аккаунту происходит крайне просто:

После привязки токена он становится вторым фактором по умолчанию, при этом нельзя отключить альтернативный способ: либо SMS, либо TOTP.

Альтернативным вторым фактором я выбрал TOTP. Я использую программную реализацию TOTP через 1Password (то же, что и Google Authenticator, только на десктопе). Yubikey NEO тоже умеет TOTP, при этом ключ для генерации паролей сохраняется в токене и не может быть извлечен. Но так как пароли генерируются на основании времени, нужно держать запущенным программный апплет для передачи времени в токен, что мне не понравилось.
Я также бегло исследовал другие функции устройства.
OpenPGP карта сразу заработала с GnuPG 2.0.27 из пакета gpgtools.org.
gpg --card-status
Application ID . F3427001240104000006010230340000 Version . 2.0 Manufacturer . Yubico Serial number . 1023034 Name of cardholder: [not set] Language prefs . [not set] Sex . unspecified URL of public key : [not set] Login data . [not set] Signature PIN . forced Key attributes . 2048R 2048R 2048R Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 0 Signature key . [none] Encryption key. [none] Authentication key: [none] General key info. [none]
Карта версии 2.0, ключи только RSA и не длиннее 2048 бит.
Работа с картой возможна и через NFC, например, на Android с помощью http://www.openkeychain.org/. Прелесть такой связки в том, что все операции с закрытым ключом выполняются на карте, ключ никогда не покидает карту и не может быть извлечен из нее.
К сожалению, на днях была найдена уязвимость в реализации OpenPGP в Yubikey NEO, позволяющая обойти ввод пин-кода и выполнить операцию с приватным ключом. И, так как обновление прошивки на устройствах запрещено из соображений безопасности, исправить баг нет возможности. Компания Yubico обещает заменить кривые железки всем желающим.
У меня как раз оказалась уязвимая версия прошивки 1.0.8
Эмуляция Mifare Classic — самая непонятная для меня функция. При попытке общаться с ней, как с обычным Mifare Classic, карта ведет себя странно.
вывод libnfc с попытками авторизоваться
$ LIBNFC_LOG_LEVEL=3 ./readmifare1k.py -s 115200 -l /dev/tty.SLAB_USBtoUART debug libnfc.config key: [allow_autoscan], value: [false] debug libnfc.config key: [allow_intrusive_scan], value: [false] debug libnfc.config key: [log_level], value: [1] debug libnfc.config key: [device.name], value: [microBuilder.eu] debug libnfc.config key: [device.connstring], value: [pn532_uart:/dev/tty.SLAB_USBtoUART] debug libnfc.config Unable to open directory: /usr/local/etc/nfc/devices.d debug libnfc.general log_level is set to 3 debug libnfc.general allow_autoscan is set to false debug libnfc.general allow_intrusive_scan is set to false debug libnfc.general 1 device(s) defined by user debug libnfc.general #0 name: "microBuilder.eu", connstring: "pn532_uart:/dev/tty.SLAB_USBtoUART" debug libnfc.driver.pn532_uart Attempt to open: /dev/tty.SLAB_USBtoUART at 115200 baud. debug libnfc.bus.uart Serial port speed requested to be set to 115200 baud. debug libnfc.chip.pn53x Diagnose debug libnfc.chip.pn53x Timeout value: 500 debug libnfc.bus.uart TX: 55 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 debug libnfc.chip.pn53x SAMConfiguration debug libnfc.chip.pn53x Timeout value: 1000 debug libnfc.bus.uart TX: 00 00 ff 03 fd d4 14 01 17 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 15 debug libnfc.bus.uart RX: 16 00 debug libnfc.bus.uart TX: 00 00 ff 09 f7 d4 00 00 6c 69 62 6e 66 63 be 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 09 f7 debug libnfc.bus.uart RX: d5 01 debug libnfc.bus.uart RX: 00 6c 69 62 6e 66 63 debug libnfc.bus.uart RX: bc 00 debug libnfc.chip.pn53x GetFirmwareVersion debug libnfc.bus.uart TX: 00 00 ff 02 fe d4 02 2a 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 06 fa debug libnfc.bus.uart RX: d5 03 debug libnfc.bus.uart RX: 32 01 06 07 debug libnfc.bus.uart RX: e8 00 debug libnfc.chip.pn53x SetParameters debug libnfc.bus.uart TX: 00 00 ff 03 fd d4 12 14 06 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 13 debug libnfc.bus.uart RX: 18 00 debug libnfc.general "pn532_uart:/dev/tty.SLAB_USBtoUART" (pn532_uart:/dev/tty.SLAB_USBtoUART) has been claimed. debug libnfc.chip.pn53x ReadRegister debug libnfc.bus.uart TX: 00 00 ff 0c f4 d4 06 63 02 63 03 63 0d 63 38 63 3d b0 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 07 f9 debug libnfc.bus.uart RX: d5 07 debug libnfc.bus.uart RX: 00 00 00 00 00 debug libnfc.bus.uart RX: 24 00 debug libnfc.chip.pn53x PN53X_REG_CIU_TxMode (Defines the transmission data rate and framing during transmission) debug libnfc.chip.pn53x PN53X_REG_CIU_RxMode (Defines the transmission data rate and framing during receiving) debug libnfc.chip.pn53x WriteRegister debug libnfc.bus.uart TX: 00 00 ff 08 f8 d4 08 63 02 80 63 03 80 59 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 09 debug libnfc.bus.uart RX: 22 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 00 f9 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 01 f8 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 06 fa d4 32 05 ff ff ff f8 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x ReadRegister debug libnfc.bus.uart TX: 00 00 ff 0e f2 d4 06 63 02 63 03 63 05 63 38 63 3c 63 3d 19 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 08 f8 debug libnfc.bus.uart RX: d5 07 debug libnfc.bus.uart RX: 80 80 00 00 00 00 debug libnfc.bus.uart RX: 24 00 debug libnfc.chip.pn53x PN53X_REG_CIU_TxAuto (Controls the settings of the antenna driver) debug libnfc.chip.pn53x PN53X_REG_CIU_Control (Contains miscellaneous control bits) debug libnfc.chip.pn53x WriteRegister debug libnfc.bus.uart TX: 00 00 ff 08 f8 d4 08 63 05 40 63 3c 10 cd 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 09 debug libnfc.bus.uart RX: 22 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 00 f9 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 06 fa d4 32 05 00 01 02 f2 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x ReadRegister debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 06 63 03 c0 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 03 fd debug libnfc.bus.uart RX: d5 07 debug libnfc.bus.uart RX: 80 debug libnfc.bus.uart RX: a4 00 debug libnfc.chip.pn53x PN53X_REG_CIU_RxMode (Defines the transmission data rate and framing during receiving) debug libnfc.chip.pn53x WriteRegister debug libnfc.bus.uart TX: 00 00 ff 05 fb d4 08 63 03 88 36 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 09 debug libnfc.bus.uart RX: 22 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 01 f8 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 00 f9 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 01 f8 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 00 f9 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 01 f8 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 06 fa d4 32 05 00 01 02 f2 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x InListPassiveTarget debug libnfc.chip.pn53x No timeout debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 4a 01 00 e1 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 20 e0 debug libnfc.bus.uart RX: d5 4b debug libnfc.bus.uart RX: 01 01 00 44 28 07 04 1b 15 4a 0e 35 80 11 78 f7 b1 02 59 75 62 69 6b 65 79 4e 45 4f 72 33 debug libnfc.bus.uart RX: 8e 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 00 f9 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 01 f8 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 06 fa d4 32 05 00 01 02 f2 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x InListPassiveTarget debug libnfc.chip.pn53x No timeout debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 4a 01 00 e1 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 20 e0 debug libnfc.bus.uart RX: d5 4b debug libnfc.bus.uart RX: 01 01 00 44 28 07 04 1b 15 4a 0e 35 80 11 78 f7 b1 02 59 75 62 69 6b 65 79 4e 45 4f 72 33 debug libnfc.bus.uart RX: 8e 00 debug libnfc.chip.pn53x SetParameters debug libnfc.bus.uart TX: 00 00 ff 03 fd d4 12 04 16 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 13 debug libnfc.bus.uart RX: 18 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 00 f9 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 32 01 01 f8 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x RFConfiguration debug libnfc.bus.uart TX: 00 00 ff 06 fa d4 32 05 00 01 02 f2 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 02 fe debug libnfc.bus.uart RX: d5 33 debug libnfc.bus.uart RX: f8 00 debug libnfc.chip.pn53x InListPassiveTarget debug libnfc.chip.pn53x No timeout debug libnfc.bus.uart TX: 00 00 ff 04 fc d4 4a 01 00 e1 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 0f f1 debug libnfc.bus.uart RX: d5 4b debug libnfc.bus.uart RX: 01 01 00 44 28 07 04 1b 15 4a 0e 35 80 debug libnfc.bus.uart RX: 2a 00 debug libnfc.chip.pn53x InDataExchange debug libnfc.bus.uart TX: 00 00 ff 12 ee d4 40 01 60 00 a0 a1 a2 a3 a4 a5 04 1b 15 4a 0e 35 80 7b 00 debug libnfc.bus.uart RX: 00 00 ff 00 ff 00 debug libnfc.chip.pn53x PN53x ACKed debug libnfc.bus.uart RX: 00 00 ff 01 ff debug libnfc.bus.uart RX: 7f 81 00 error libnfc.driver.pn532_uart Application level error detected
Карта имеет 7-байтный UID
ATQA (SENS_RES): 00 44 UID (NFCID1): 04 1b b1 4e f7 00 f1 SAK (SEL_RES): 28 ATS: 78 f7 b1 02 59 75 62 69 6b 65 79 4e 45 4f 72 33
Физически RFID-метка работает довольно хорошо, несмотря на маленькую антенну, ридер в метро «схватывает» с 3 сантиметров.
Заключение
По сравнению со всеми аппаратными токенами, которыми мне доводилось пользоваться, технология U2F — это крайне удобно. Не нужно возиться с импортом сертификатов, установкой драйверов, никаких Java-апплетов и прочего.
Я протестировал работу на Windows 7, Mac OS 10.10 и Ubuntu 14.0.4. Во всех системах Chrome сразу подхватывал токен без установки драйверов. В целом, развертывание видится настолько простым и понятным, что справится даже ребенок.
А наличие полностью открытых спецификаций, плагинов и библиотек позволит прикручивать U2F к любым приложениям.
Error u2f not supported что это
If you see the "U2F not supported" error, this means that your browser does not (properly) support the U2F protocol. This protocol is used by MyCrypto to connect with your hardware wallet.
To solve this issue, you can try using a different browser, such as Google Chrome. You can also use the MyCrypto desktop application. If you are on Android and want to use your Ledger Wallet, you can try using the Ledger U2F Bridge app.
Share
MyCrypto is the number one way to manage all of your Ethereum Accounts
You can always email us for one-on-one help using support@mycrypto.com
Send Us A Message
Didn't find what you were looking for? Contact Us
MyCrypto is an open-source tool that allows you to manage your Ethereum accounts privately and securely. Developed by and for the community since 2015, we’re focused on building awesome products that put the power in people’s hands.
FIDO2 — Пароли must die 04.06.2018 08:18
Думаю, все вы неоднократно слышали о том что «пароли мертвы», «пароли вымирают», «новая технология убьет пароли» и тому подобное.
Мы в FIDO Alliance как раз-таки пришли сообщить вам о том, что пароли все-таки вымрут… в аутентификации.
Прежде чем мы начнем разговор о массовом уничтожении многословных гадов, давайте вернемся к нашему самому популярному протоколу FIDO U2F о коем я писал ранее.

То есть сценарий аутентификации с U2F таков:
Регистрация:
— Пользователь регистрируется, используя имя пользователя (может лучше поменять на пароль, а то пользователь-пользователь?) и пароль
— Сервер хеширует пароль с использованием scrypt, argon2, bcrypt и сохраняет в БД
— Пользователь добавляет свое устройство, храня на сервере публичный ключ и id пары ключей на устройстве
Аутентификация:
— Пользователь вводит логин и пароль
— Сервер хеширует пароль и сравнивает с хешем в базе данных
— Сервер генерирует случайный «вызов» и отправляет клиенту вместе с ID
— Клиент передает вызов, id, token binding, и origin сессии U2F токену
— Аутентификатор все это подписывает приватным ключом и отправляет клиенту, а тот серверу
— Профит
На сегодняшний день мультифакторная аутентификация с использованием U2F является самым легким, фишинг устойчивым и безопасным методом аутентификации. Но даже у этого метода есть свои недостатки.

Пароли все еще можно украсть на всех стадиях аутентификации:
— Можно украсть с помощью кейлоггера;
— Можно украсть при проблемах с TLS (см Heartbleed);
— Можно украсть если сервер уязвим к инъекции кода, или при ошибках в коде (см Twitter)
— Можно украсть если пароли слабо хешированы или не были хешированы вовсе.
Пока есть пароль, его можно украсть
А что если убрать пароль вообще?
Собственно, так подумали мы в FIDO Alliance (мы не имеем ничего общего с гипертекстовым фидонетом, хотя потенциально можем быть там использованы) и сделали FIDO2

Для тех, кто о нас не слышал, FIDO Alliance — это консорциум, разрабатывающий открытые стандарты безопасной аутентификации. Выше на картинке вы можете видеть наших членов совета, которые собственно и разрабатывают стандарты.
FIDO2 — это наш последний проект, который мы разрабатывали более трех лет. Он состоит из двух частей:
— WebAuthn — JS API для менеджмента учетных записей на публичных ключах. Это W3C стандарт, так что будет обязателен для всех браузеров. Собственно Chrome, Firefox и Edge уже публично заявили о работе над его поддержкой.
— CTAP2 — Client-to-Authenticator 2 — это стандарт, описывающий CBOR протокол для общения с аутентификатором по USB, NFC и BLE.
Пользователь

Для пользователя это просто:
— Пользователь вводит имя
— Проходит верификацию
— Профит!
Протокол
FIDO2 — это член семейства вызов-ответ протоколов FIDO. В протоколе есть шесть основных механизмов безопасности:
1. Вызов-ответ

Первый механизм это вызов-ответ. Сервер генерирует случайный вызов и отправляет его клиенту. Клиент передает данный вызов аутентификатору, который подписывает вызов и возвращает его клиенту, а тот в свою очередь серверу. Сервер, зная вызов, подпись и публичный ключ, может подтвердить подпись и таким образом аутентифицировать клиента.
2. Фишинг-защита

Второй механизм это сессионно-зависимая транзакция. Когда клиент получает вызов от сервера, он добавляет к вызову информацию о сессии: origin (прим: example.com), token binding. Эта информация подписывается аутентификатором и возвращается серверу. Сервер декодирует ответ и смотрит или в источником был он сам, и если пользователь подвергся фишинг атаке то сервер сможет увидеть что источником был на пример attacker.com, а не example.com и таким образом предотвратить атаку.
3. Защита от атаки повторного воспроизведения

Чтобы защитить от атаки повторного воспроизведения, в транзакции присутствует счетчик, который увеличивается на единицу при каждой операции. Если сервер получил ответ со счетчиком, значение которого меньше или равно последнему сохраненному значению, то сервер может точно сказать что это атака повторного воспроизведения.
4. Приватность

Четвертый механизм защиты это регистрационно-уникальные пары ключей. При каждой регистрации аутентификатор генерирует случайную пару ключей со случайным идентификатором. Таким образом даже если вы и ваш партнер будете использовать один аутентификатор для обоих аккаунтов, то сервер не сможет узнать этого.
При аутентификации идентификатор пары ключей передается аутентификатору, и тот, используя origin и идентификатор, найдет вашу пару ключей в своей защищенной БД и вернет подпись.

Альтернатива к передаче идентификатора это использование резидентных ключей (RK, resident keys). При аутентификации аутентификатор вернет подписи для всех RK пар ключей. Клиент предоставляет пользователю выбор пары и вернет подпись серверу. Более подробно RK я распишу ниже.
5. Аттестация

Пятый механизм это аттестация. Иногда сайту нужно узнать тип устройства у пользователя. Так например в США все государственные учреждения обязаны использовать только FIPS (Federal Information Processing Standards) сертифицированные устройства. Подобные требования есть во Франции, Израиле, России и других странах. Для всего этого и существует аттестация.
При производстве аутентификаторов, на каждые сто тысяч устройств компания генерирует «сертификат партии» и ключи к нему и устанавливает их на каждое устройство. При регистрации устройство подписывает всю информацию приватным ключом партийного сертификата и возвращает сертификат вместо публичного ключа. В сертификате содержится информация о аутентификаторе, и его AAGUID (Authenticator Attestation GUID). Также при получении FIDO сертификации компания выпускает специальный документ метадаты, или просто метадату, и помещает в наше хранилище метадаты доступное всем. В метадате содержится информация о аутентификаторе, включая его криптографические характеристики, биометрические характеристики если он поддерживает биометрику, алгоритмы, уровни безопасности, базовое описание и много другой информации., а основе имеющейся информации сервер может судить о том, стоит ли ему принимать аутентификатор или нет.
Аттестация бывает разная. Существует полная версия аттестации, в которой сервер возвращает сертификат. Есть само-аттестация, при которой устройство не поддерживает сертификаты, а вместо этого возвращает публичный ключ только что сгенерированной пары.
Также пользователь может сам настроить метод, с помощью которого он хочет вернуть аттестацию. Так например пользователь может вообще запретить возвращать аттестацию и клиент просто удалит её, вернув регистрационный ответ без аттестации. Об этом я расскажу позже.
6. Тест на наличие пользователя
Одно из фундаментальных требований FIDO это тест на наличие пользователя. В данном случае имеется в виду, что аутентификатор обязан удостоверится в присутствии пользователя… Это может быть сделано по-разному: простое нажатие на кнопку, отпечаток, пин-код и другое.
WebAuthn
В этой секции мы рассмотрим JS API для работы с FIDO2.Credential Management API
WebAuthn это дополнения к Credential Management API для менеджмента учетных записей публичных ключей. CredMan API это API (неожиданно!) для менеджмента учетных данных пользователя или если выразиться проще: это API для доступа к автозаполнению в браузере.
Далее мы рассмотрим пример создания учетных данных:
navigator.credentials.store(< 'type': 'password', 'id': 'alice', 'password': 'VeryRandomPassword123456' >)
А вот пример запроса учетных данных и последующего использования их для аутентификации:
navigator.credentials .get(< 'password': true >) .then(credential => < if (!credential) < throw new Error('No credentials returned!') >let credentials = < 'username': credential.id, 'password': credential.password >return fetch('https://example.com/loginEndpoint', < method: 'POST', body: JSON.stringify(credentials), credentials: 'include' >) >) .then((response) => < . >)
Джеймс Аллардайс сделал прекрасную презентацию в прошлом году по CredManAPI
pusher.com/sessions/meetup/js-monthly-london/building-a-better-login-with-the-credential-management-api
Create public-key credential
Для создания Public-Key Credential мы будем использовать navigator.credentials.create метод, передав ему CreateCredential объект типа «publicKey».
var randomChallengeBuffer = new Uint8Array(32); window.crypto.getRandomValues(randomChallengeBuffer); var base64id = 'MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII=' var idBuffer = Uint8Array.from(window.atob(base64id), c=>c.charCodeAt(0)) var publicKey = < challenge: randomChallengeBuffer, rp: < name: "FIDO Example Corporation" >, user: < id: idBuffer, name: "alice@example.com", displayName: "Alice von Wunderland" >, attestation: 'direct', pubKeyCredParams: [ < type: 'public-key', alg: -7 >, // ES256 < type: 'public-key', alg: -257 >// RS256 ] > // Note: The following call will cause the authenticator to display UI. navigator.credentials.create(< publicKey >) .then((newCredentialInfo) => < console.log('SUCCESS', newCredentialInfo) >) .catch((error) => < console.log('FAIL', error) >)
Думаю, код говорит сам за себя, но отмечу при этом несколько моментов:
— challenge и user.id должны быть буферами
— pubKeyCredParams — это список алгоритмов, которые поддерживает сервер. В данный момент сертифицированные сервера FIDO2 обязаны поддерживать: RSA-PSS 2048 с SHA256/384/512, RSA-PKCS1_3 с SHA256/384/512/1, EC с SHA256/384/512, а также кривые secp256/384/521p1(NIST) и secp256k1, и EdDSA ED25519.
— attestation — это собственно вид аттестации, возвращаемой клиентом. Есть три возможные значения: none, direct, indirect. Direct это, собственно, классическая аттестация. None это полное отсутствие аттестации, при котором клиент просто удалит всю аттестационную секцию и заменит AAGUID в ответе на 0×00000000000000000000000000000000. Indirect это аттестация через privacy-ca. По-умолчанию attestation установлена на none. То есть если вы хотите аттестацию, то надо это чётко указать в параметрах. При этом необходимо учитывать, что пользователь все равно может вам отказать в аттестации и вернуть 'none' если он того захочет.

Вот пример пример того как пользователь может контролировать аттестацию в Firefox Nightly

В ответ вы получите аттестационный объект:
Здесь вы можете видеть:
— id/rawId — это идентификатор пары ключей на устройстве или credId. id это base64url закодированная версия буфера rawId.
— response.clientDataJSON — это буфер CollectedDataJSON, JSON объекта содержащего сессионную информацию и сам вызов. Пример декодированного clientDataJSON:
< "challenge": "1KnytoY-it44IiEMx0lK5GBlBvAJeVULPSCw5E-5qpA", "origin": "http://localhost:3000", "tokenBinding": < "status": "not-supported" >, "type": "webauthn.create" >
— attestationObject — это CBOR объект, содержащий аттестацию, информацию об аутентификаторе, флаги, счётчик и публичный ключ.

— authData — это сырой буфер, содержащий хеш источника или rpIdHash, флаги, счетчик, идентификатор пары ключей, блок с аттестационной информацией и информацию от расширений.
— fmt — это формат аттестации. В данный момент WebAuthn поддерживает «packed», «fido-u2f», «android», «tpm» и «safety-net» аттестации.
— attStmt — это собственно информация по аттестации. Подпись, сертификаты и так далее.
Для верификации подписи мы высчитываем хеш clientDataJSON и получаем clientDataHash. Затем мы объединяем authData и clientDataHash и получаем signatureBase. И в конце мы подтверждаем подпись с помощью attStmt.sig, сертификата или публичного ключа пользователя и signatureBase.

Для того чтобы получить аутентификационую подпись мы будем использовать navigator.credentials.create метод, передав ему объект типа «publicKey».
var randomChallengeBuffer = new Uint8Array (32);
window.crypto.getRandomValues (randomChallengeBuffer);
var idBuffer = encoder.encode("mFuXJYt-0qYZDUBFyN_SW_Cach6U56mrnHA_ZuxtlOnjHLhjfWjYVftbxr4WMmxp1-MG3nRRNQoI7WvvAM0pmw") var options = < challenge: randomChallengeBuffer, allowCredentials: [< type: "public-key", id: idBuffer >] > navigator.credentials.get(< "publicKey": options >) .then((assertion) => < console.log('SUCCESS', assertion) >) .catch((error) => < console.log('FAIL', error) >)
allowCredentials — это список разрешенных учетных записей, которые идентифицируются идентификатором пары ключей на устройстве (credId). Для двухфакторной аутентификации вы всегда обязаны передавать allowCredentials c credId в запросе. Если во время создания учетной записи мы установили флаг authenticatorSelection.requireResidentialKey, то в дальнейшем обязаны не добавлять поле allowCredentials.

В ответ получаем вот такой объект:
Как вы видите, структура очень похожа, но есть несколько различий:
— clientDataJSON.type теперь типа «webauthn.get»
< "challenge": "-0NPkC-1zxpcGanUJMbKFdd7Ze0kRphWFy1_Sgc4FpI", "origin": "http://localhost:3000", "tokenBinding": < "status": "not-supported" >, "type": "webauthn.get" >
— attestationObject отсутствует
— authenticatorData это authData, но теперь без authenticatorAttestation секции
— signature это подпись
— userHandle — это идентификатор пользователя, который вы передали во время регистрации в поле user.id
Вычисление подписи работает так же, как и при создании учетной записи.
На этом я закончу первую часть из цикла статей. В следующей части мы разберем протокол общения клиента и аутентификатора CTAP2(Client-to-Authenticator 2).
Большая благодарность Павлу Замятину за редактуру и орфографию.